タイトルが誤解を招くものでないことを願っています。onRetainNonConfigurationInstance()
画像のAsyncTask
読み込みを実装しようとしていますが、このエラーが発生しています"Java.lang.RuntimeException:Unable to retain Activity"
。これが私のコードですonRetainNonConfigurationInstance()
:
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();
}
}
ListView
エラーから取得する前に最初にルート要素を取得する必要があると想定してlogcat
いますが、方法がわかりません。ドキュメントから適切なメソッドを見つけることができないようです。
PS: 私は ではActivity
なくを使用していListActivity
ます。