我对这个错误感到困惑 -
只有创建视图层次结构的原始线程才能接触其视图。
我有一个类,它在 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 方法中有几个不同的断点,但在调试时都没有到达它们。 . 非常令人沮丧.. 有什么想法吗?