我希望標題不會誤導。我試圖執行加載圖像的AsyncTask
的onRetainNonConfigurationInstance()
,我得到這個錯誤"Java.lang.RuntimeException:Unable to retain Activity"
。這裏是我的onRetainNonConfigurationInstance()
代碼:從異步任務onRetainNonConfigurationInstance()中獲取ListView中的LinearLayout
public Object onRetainNonConfigurationInstance(){
//final ListView listview = list;
final int count = list.getChildCount();
final LoadedImage[] mylist = new LoadedImage[count];
for(int i = 0; i < count; i++){
final ImageView v = (ImageView)list.getChildAt(i); // getting error here
mylist[i] = new LoadedImage(((BitmapDrawable) v.getDrawable()).getBitmap());
}
return mylist;
}
這裏是Logcat
:
05-18 08:43:15.385: E/AndroidRuntime(28130): java.lang.RuntimeException: Unable to retain activity {com.MyApps.ImageGen/com.MyApps.ImageGen.Wallpapers}: java.lang.ClassCastException: android.widget.LinearLayout
05-18 08:43:15.385: E/AndroidRuntime(28130): at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:2989)
05-18 08:43:15.385: E/AndroidRuntime(28130): at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3100)
05-18 08:43:15.385: E/AndroidRuntime(28130): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3216)
05-18 08:43:15.385: E/AndroidRuntime(28130): at android.app.ActivityThread.access$1600(ActivityThread.java:132)
這裏是我的佈局與ListView
:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:cacheColorHint="#00000000"
android:listSelector="@android:color/transparent" >
</ListView>
</LinearLayout>
下面是我設置了ListView
:
private void setupViews() {
list = (ListView)findViewById(android.R.id.list);
list.setDivider(null);
list.setDividerHeight(0);
imageAdapter = new ImageAdapter(getApplicationContext());
list.setAdapter(imageAdapter);
list.setOnItemClickListener(this);
}
我的異步任務和項目適配器:異步任務中
class LoadImagesFromSDCard extends AsyncTask<Object, LoadedImage, Object> {
@Override
protected Object doInBackground(Object... params) {
Bitmap bitmap = null;
Bitmap newbitmap = null;
Uri uri = null;
String [] img = {MediaStore.Images.Media._ID};
String state = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(state)){
cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, img, null, null, null);
} else {
// cursor = getContentResolver().query(MediaStore.Images.Media.INTERNAL_CONTENT_URI, img, null, null, null);
inInternalStorage = true;
}
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID);
int size = cursor.getCount();
if(size == 0){
//Toast.makeText(getApplicationContext(), "There are no Images on the sdcard", Toast.LENGTH_SHORT).show();
//System.out.println("size equals zero");
Wallpaper.this.runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(getApplicationContext(), "There are no Images on the sdcard", Toast.LENGTH_SHORT).show();
}
});
return params;
}else {
}
for(int i = 0; i < size; i++){
cursor.moveToPosition(i);
int ImageId = cursor.getInt(column_index);
if(inInternalStorage == true){
uri = Uri.withAppendedPath(MediaStore.Images.Media.INTERNAL_CONTENT_URI, "" + ImageId);
}else {
uri = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + ImageId);
}
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
Log.i(TAG, "imageheight = " + imageHeight);
Log.i(TAG, "imagewidth = " + imageWidth);
Log.i(TAG, "imageType = " + imageType);
//options.inSampleSize=4;
options.inSampleSize = calculateInSampleSize(options, imageWidth, imageHeight);
options.inJustDecodeBounds = false;
//bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
if(bitmap != null){
newbitmap = Bitmap.createScaledBitmap(bitmap, 180, 180, true);
bitmap.recycle();
}
if(newbitmap != null){
publishProgress(new LoadedImage(newbitmap));
}
}catch(IOException e){
}
//cursor.close();
}
cursor.close();
return null;
}
@Override
public void onProgressUpdate(LoadedImage... value){
addImage(value);
}
@Override
protected void onPostExecute(Object result) {
setProgressBarIndeterminateVisibility(false);
}
}
private static class LoadedImage {
Bitmap mBitmap;
LoadedImage(Bitmap bitmap) {
mBitmap = bitmap;
}
public Bitmap getBitmap() {
return mBitmap;
}
}
/*Image Adapter to populate grid view of images*/
public class ImageAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<LoadedImage> photos = new ArrayList<LoadedImage>();
public ImageAdapter(Context context){
this.mContext = context;
}
public void addPhotos(LoadedImage photo){
photos.add(photo);
}
@Override
public int getCount() {
return photos.size();
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView image;
ViewHolder holder;
if(convertView == null){
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//convertView = inflater.inflate(R.layout.image_list,null);
convertView = inflater.inflate(R.layout.media_view, null);
holder = new ViewHolder();
holder.image = (ImageView)convertView.findViewById(R.id.media_image_id);
//holder.item_name = (TextView)convertView.findViewById(R.id.media_image_id);
convertView.setTag(holder);
} else{
holder = (ViewHolder)convertView.getTag();
}
//holder.image.setLayoutParams(new GridView.LayoutParams(100, 100));
//String item_name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME));
holder.image.setImageBitmap(photos.get(position).getBitmap());
//holder.item_name.setText(item_name);
return convertView;
}
}
static class ViewHolder {
ImageView image;
TextView item_name;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Cursor cursor = null;
int image_column_index = 0;
String[] proj = {MediaStore.Images.Media.DATA};
String state = Environment.getExternalStorageState();
if(Environment.MEDIA_MOUNTED.equals(state)){
cursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,proj,null, null,null);
}else{
cursor = managedQuery(MediaStore.Images.Media.INTERNAL_CONTENT_URI,proj,null, null,null);
}
cursor.moveToPosition(position);
image_column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
String info = cursor.getString(image_column_index);
Intent imageviewer = new Intent(getApplicationContext(), ViewImage.class);
imageviewer.putExtra("pic_name", info);
startActivity(imageviewer);
cursor.close();
}
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 2;
if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float)height/(float)reqHeight);
} else {
inSampleSize = Math.round((float)width/(float)reqWidth);
}
}
/*final int REQUIRED_SIZE = 180;
int scale = 1;
if(reqWidth > REQUIRED_SIZE || reqHeight > REQUIRED_SIZE){
scale = (int)Math.pow(2, (int)Math.round(Math.log(REQUIRED_SIZE/(double)Math.max(reqHeight, reqWidth))/Math.log(0.5)));
}*/
return inSampleSize;
}
其他方法:
private void loadImages() {
final Object data = getLastNonConfigurationInstance();
if(data == null){
new LoadImagesFromSDCard().execute();
}else {
final LoadedImage[] photos = (LoadedImage[])data;
if(photos.length == 0){
new LoadImagesFromSDCard().execute();
}
for(LoadedImage photo:photos){
addImage(photo);
}
}
}
private void addImage(LoadedImage... value) {
for(LoadedImage photo: value){
imageAdapter.addPhotos(photo);
imageAdapter.notifyDataSetChanged();
}
}
我假設我應該先把根元素之前,我從logcat
錯誤ListView
,但我不知道如何,我似乎無法從文檔中找到合適的方法。
P.S:我正在使用Activity
而不是ListActivity
。
感謝,它的工作原理,但唯一的麻煩,現在是,最後的圖像顯示在屏幕上時,屏幕方向變化僅在新的方向的佈局被顯示;但是您可以看到圖像仍在後臺加載。特別是當一個人點擊圖像時,它會在列表中顯示正確的圖像,但屏幕仍然顯示在方向中可見的最後一個圖像。希望我在這方面有所瞭解。任何想法如何解決它? – irobotxxx
@sparrow我不明白,編輯你的問題,嘗試更好地解釋(並且發佈'AsyncTask'代碼和你設置圖像的自定義適配器(如果有的話))。當有方向改變時,活動將被重新創建,但'AsyncTask'將繼續執行它的後臺任務(所以在後臺看到它是正常的)。您可能只會看到最後一個可見圖像,因爲這些是您發送到新活動的唯一圖像。 – Luksprog
我的意思是這樣的..如果我通過我在垂直方向滾動列表,當我切換到水平方向時,最後的可見光圖像(可以說4張圖片),現在在水平方向顯示和滾動足夠大剛爲那些可見的4張圖片。現在,如果我滾動以便我只能在水平方向上在屏幕上看到2個圖像,當我切換回垂直方向時,只有這2個圖像現在在屏幕上。它像它一直在切割它們。我發佈了我的異步任務和適配器代碼。 – irobotxxx