0

我对这个错误感到困惑 -

只有创建视图层次结构的原始线程才能接触其视图。

我有一个类,它在 UI 的可运行/线程块中调用。没有尝试-据我所知???- 用于操作该可运行文件或它调用的类中的 UI,如下所示......

public class MonthSort {
Handler handler;
int imageWidth;
List<PhotoData> photoList;
public MonthSort(Handler handler2, int width, List<PhotoData> pList) {
    photoList = new ArrayList<PhotoData>();
    photoList = pList;
    imageWidth = width;
    handler = handler2;
}

public void sortFiles()
{
    int month, photoCount;
    File fileName = new File("");
    Message msg = handler.obtainMessage();
    for (int i = 0; i < 12; i++) {
        month = i + 1;
        photoCount = 0;
        for (PhotoData pd : photoList) {
            if(month == pd.month)
            {
                if(photoCount == 0)
                    fileName = pd.fileName;
                photoCount++;
            }
        }
        if(photoCount != 0)
        {

            Bundle bundle = new Bundle();
            bundle.putString("filename", fileName.toString());
            bundle.putInt("month", month);
            bundle.putInt("count", photoCount);
            byte[] thumbNail = getThumbnail(fileName, imageWidth);
            bundle.putByteArray("thumbnail", thumbNail);
            msg.setData(bundle);
            handler.dispatchMessage(msg);

        }
    }
    Bundle bundle = new Bundle();
    bundle.putBoolean("end", true);
    msg.setData(bundle);
    handler.dispatchMessage(msg);
}

private byte[] getThumbnail(File file, int size)
{
    /** The object of this code is to reduce the bitmap for thumbnail display,
     * Not just to reduce dimensions, but to reduce the physical size of the 
     * bitmap ready, so that several bitmaps can remain in memory without 
     * an outOfMemoryException error.*/
    byte[] thumbnail;
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    Bitmap bitmap = BitmapFactory.decodeFile(
            file.toString(), options);
    options.inSampleSize = calculateInSampleSize(
            options, imageWidth, imageWidth);
    options.inJustDecodeBounds = false;
    bitmap = BitmapFactory.decodeFile(file.toString(),
            options);
     /*now the size of the Bitmap is manageable, we set about sizing the 
     * thumbnail correctly, preserving the Aspect Ratio */

    final int REQUIRED_SIZE = imageWidth;
    int thumbHeight = REQUIRED_SIZE, thumbWidth = REQUIRED_SIZE;
    float ratio = (float) bitmap.getWidth() // Work out the aspect ratio.
            / (float) bitmap.getHeight();
    if (ratio == 1) {
        thumbHeight = REQUIRED_SIZE;
        thumbWidth = REQUIRED_SIZE;
    } else if (ratio < 1) {
        thumbHeight = REQUIRED_SIZE;
        thumbWidth = (int) ((float) REQUIRED_SIZE * (float) ratio);
    } else {
        thumbWidth = REQUIRED_SIZE;
        thumbHeight = (int) ((float) REQUIRED_SIZE / (float) ratio);
    }
    Bitmap bitmap2 = Bitmap.createScaledBitmap(
            bitmap, thumbWidth, thumbHeight, false);

    ByteArrayOutputStream out;
    try {
        out = new ByteArrayOutputStream();

        bitmap2.compress(CompressFormat.JPEG, 30, out); // Compress the bitmap   
        thumbnail = out.toByteArray();
        out.close(); // close the out stream.
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        thumbnail = new byte[1];
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        thumbnail = new byte[1];
    }
    return thumbnail;
}

private int calculateInSampleSize(Options options, int reqWidth, int reqHeight) {
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if(height > reqHeight || width > reqWidth)
    {
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
    return inSampleSize;
}

主线程像往常一样在顶部有处理程序(参见下面的代码 - 只是为了简洁起见的处理程序代码),并使用自定义适配器的 notifyDataSetChanged() 方法(包括代码)......

public class MonthActivity extends Activity {
List<PhotoData> photoList;
static List<MonthData> photos;
int imageWidth;
GridView photoGrid;
static ImageAdapter2 iAdapter2;
static int year;
Thread monthSortThread;

static Handler handler2 = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message msg) 
    {
        super.handleMessage(msg);
        Bundle bundle = msg.getData();  // Get the message sent to the Handler.
        boolean ended = bundle.getBoolean("end");
        if(ended)
        {
            iAdapter2.notifyDataSetChanged();
            //Toast.makeText(getBaseContext(), "FINISHED !!!", Toast.LENGTH_LONG).show();
        } else
        {
            MonthData md = new MonthData();
            md.monthValue = bundle.getInt("month");
            md.monthString = getMonthString(md.monthValue);
            Log.d("Debug", md.monthString + " " + String.valueOf(year));
            md.count = bundle.getInt("count");
            byte[] tn = bundle.getByteArray("thumbnail");
            md.thumbnail =  BitmapFactory.decodeByteArray(tn, 0, tn.length);
            photos.add(md);
            iAdapter2.notifyDataSetChanged();
        }
    }
};

(适配器代码)

public class ImageAdapter2 extends BaseAdapter{
List<MonthData> photos;
Context context;
int year, imageWidth;
public ImageAdapter2 (Context ct, List<MonthData> pList, int yr, int i) {
    photos = new ArrayList<MonthData>();
    photos = pList;
    context = ct;
    year = yr;
    imageWidth = i;
}

@Override
public int getCount() {
    return photos.size();
}

@Override
public Object getItem(int arg0) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public long getItemId(int arg0) {
    return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View myView = null;
    if(convertView == null)
    {
        LayoutInflater li = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        myView = li.inflate(R.layout.grid_cell, null);
    } else
    {
        myView = convertView;
    }
    TextView tv = (TextView)myView.findViewById(R.id.photoText);
    if(year == 0)
    {
        int count = photos.get(position).count;
        tv.setText(String.valueOf(count));
    } else
    {
        int count = photos.get(position).count;
        String month = photos.get(position).monthString;
        String yearString = String.valueOf(year);
        tv.setText(month + " " + yearString + " (" + String.valueOf(count) + ")");
    }
    ImageView iv = (ImageView)myView.findViewById(R.id.photoViewGridCell);
    iv.setScaleType(ImageView.ScaleType.CENTER_CROP);
    iv.setPadding(0, 0, 0, 0);
    iv.setLayoutParams(new LinearLayout.LayoutParams(imageWidth, imageWidth));
    iv.setMaxHeight(imageWidth);
    iv.setMaxWidth(imageWidth);
    iv.setImageBitmap(photos.get(position).thumbnail);
    return myView;
}

}

请注意,在选择自定义视图(特别是视图集合,在单独的 xml 布局文件中)时,通过 Intent 调用 MonthActivity ImageAdapter2 只是用于“启动”活动的类似适配器的一个小变体,具有略有不同的自定义视图。

此外,ImageAdapter2 已正确“连接”到所需的 Layout,并在 onCreate() 方法中启动,它甚至成功运行了构造函数,但尽管在适配器的 getView 方法中有几个不同的断点,但在调试时都没有到达它们。 . 非常令人沮丧.. 有什么想法吗?

4

1 回答 1

1

调用时将 Runnable 放入 runOnUiThread 方法中。

于 2013-04-12T17:14:42.870 回答