【问题标题】:How do I save an ArrayList<Uri> on screen rotate?如何在屏幕旋转时保存 ArrayList<Uri>?
【发布时间】:2016-12-11 08:52:30
【问题描述】:

我有一个 URI 的 ArrayList,我使用它来遍历图像并每次更新单个 ImageView。当我接近这样做时,我得到一个 NullPointerException,我相信它与相机在拍摄前面提到的照片时旋转我的屏幕(破坏活动)有关。

使用 onSaveInstanceState 和 onResume 会是什么样子?

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageURI(android.net.Uri)' on a null object reference
at plaidshorts.rafael.myapplication.Person1Screen$5.onClick(Person1Screen.java:124)
at android.view.View.performClick(View.java:5209)
at android.view.View$PerformClick.run(View.java:21174)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5477)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

第 124 行是:

mainView.setImageURI(happyList.get(0));

我的 dispatchTakePictureIntent 提示 Camera 或 Gallery 两次(参见开头的循环)。 OnActivityResult 然后获取 URI 并将其添加到 happyList(在 onCreate 中实例化)。

private void dispatchTakePictureIntent() {
    pictureCounter = -1;
    for(int i = 0; i < 2; i++) {
        pictureCounter++;
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            // Create the File where the photo should go
            File photoFile = null;
            try {
                photoFile = createImageFile();
                outputFileUri = Uri.fromFile(photoFile);
            } catch (IOException ex) {
                Log.w("error","IOException");
            }catch (NullPointerException nullEx) {
                Log.w("error","NullPointerException");
            }
            // Camera.
            final List<Intent> cameraIntents = new ArrayList<Intent>();
            final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            final PackageManager packageManager = getPackageManager();
            final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
            for (ResolveInfo res : listCam) {
                final String packageName = res.activityInfo.packageName;
                final Intent intent = new Intent(captureIntent);
                intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
                intent.setPackage(packageName);
                intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
                cameraIntents.add(intent);
            }
            // Filesystem.
            final Intent galleryIntent = new Intent();
            galleryIntent.setType("image/*");
            galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
            // Chooser of filesystem options.
            final Intent chooserIntent = Intent.createChooser(galleryIntent, "Select Source");
            // Add the camera options.
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[cameraIntents.size()]));
            startActivityForResult(chooserIntent, REQUEST_TAKE_PHOTO);
        }
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == REQUEST_TAKE_PHOTO) {
                final boolean isCamera;
                if (data == null) {
                    isCamera = true;
                } else {
                    final String action = data.getAction();
                    if (action == null) {
                        isCamera = false;
                    } else {
                        isCamera = action.equals(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                    }
                }
                Uri selectedImageUri;
                if (isCamera) {
                    selectedImageUri = outputFileUri;
                } else {
                    selectedImageUri = data == null ? null : data.getData();
                }
               // mainView.setImageURI(selectedImageUri);
               // Log.d("Before adding", selectedImageUri.toString());
                happyList.add(selectedImageUri);
            }
        }
    }

【问题讨论】:

  • 你能把你的代码和 NPE 的 logcat 一起发布吗?
  • 将您的数据存储在 onSaveInstanceState() 中并在 onRestoreInstanceState() 中恢复您的数据。欲了解更多信息,请点击此处developer.android.com/training/basics/activity-lifecycle/…
  • @MehrajMalik 我理解这些概念(大部分),但我不确定如何“存储”我的 ArrayList 并恢复它
  • 您可以在onSaveInstanceSate(Bundle outState) 上保存ArrayList&lt;String&gt;,方法是调用outState.putStringArrayList(),然后调用super.onSaveInstanceState(outState) 并在onCreate() 上检索它

标签: java android


【解决方案1】:
ArrayList<URI> uris = ..
//inStop of your application
SharedPreference sp = context.getSharePreference("imagineThis",0);
SharedPreference.Editor ed = sp.edit();
byte i =0;
for(Uri u : uris){ i++;
   ed.put(String.valueOf(i), u.toString());}
ed.commit();
//in onrestart of your app
uris.clear();//provided is not null;
SharedPreference sp = context.getSharePreference("imagineThis",0);
SharedPreference.Editor ed = sp.edit();
for(String s : ((Map<String,String>)sp.getAll()).values()){
   uris.add(Uri.parse(s));
}
ed.clear();
ed.commit();

我觉得你现在很好

【讨论】:

  • ed 名字不好,:)
【解决方案2】:

嘿,您可以简单地在您的活动中覆盖 onRetainNonConfigurationInstance 并返回您的数组列表对象,并在您的 onCreate() 方法中检查您的对象是否为空,如果它为空,则使用 getLastNonConfigurationInstance() 检索对象

//PseudoCode 
onRetainNonConfigurationInstance()  {

return arraylistObject;

}

oncreate(Bundle onSavedInstance){

if(arraylistObject == null){

arraylistObject = (cast properly)getLastNonConfigurationInstance();

}

} 

这是最简单的一种,但建议使用片段来保存跨轮换状态

【讨论】:

    【解决方案3】:

    将您的数据存储在 onSaveInstanceState() 中

    @Override
    public void onSaveInstanceState (Bundle outState) {
        // TODO Auto-generated method stub
        super.onSaveInstanceState(outState);
        outState.putSerializable("array", arrayDetails);
    }
    

    将这些代码行放入您活动的 OnCreate() 方法中,以在方向更改时获取 arrayList。

    if (savedInstanceState != null) {
          arrayDetails = (ArrayList<yourListType>)savedInstanceState.getSerializable("array");
    }
    

    【讨论】:

    • 在这种情况下,arrayDetails 是什么?我需要做一个 onResume 吗?
    • arrayDetails 是 ArrayList 你想保存在屏幕旋转。
    猜你喜欢
    • 2012-09-12
    • 2016-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多