方向变化过程中的Android应用数据丢失(Android app losing data duri

2019-08-17 03:11发布

我已经得到了我从捕获与图像的教程复制应用程序MediaStore.ACTION_IMAGE_CAPTURE 。 我已经得到了某种古怪的打算时,我的手机上运行的应用程序上。

相机应用程序本身翻转其方向运行期间几次,即使我不是移动电话。 它简单地进入横向模式返回到教程应用程序之前。 因此,控制返回到它后,图像丢失教程应用程序被翻转回到纵向模式。 我试过相机活动的方向设置为横向,图像不会丢失。

但应用程序的布局是为肖像模式。 或者,如果我认为我的相机横向同时捕捉照片,我可以把手机我的应用程序已恢复到集中后,并没有失去图像。

我没有在网络上的一些闲逛。 #2有人提到,方向的变化引起的额外通话onCreate 。 “其原因onCreate()被调用是因为当你调用纵向方向在相机的活动,它会改变方向,破坏先前的活动。” 我在用的onCreate,并在设置断点调试模式下运行应用程序onActivityResult方法。 这确实是真正onCreate当我走在纵向模式下的照片获取调用。 调用的顺序是的onCreate,onActivityResult,的onCreate。 如果我走在横向模式下的照片(这是我的相机应用最终无论哪种方式)的onCreate不会被调用。 现在,我有一些想法是怎么回事,我该如何保持这种从一个问题吗? 这里的应用程序看起来像现在:

package com.example.testapp;

import java.io.IOException;
import java.io.InputStream;

import android.app.Activity;
import android.app.WallpaperManager;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;

public class CameraActivity extends Activity implements View.OnClickListener {

    ImageButton ib;
    Button b;
    ImageView iv;
    Intent i;
    final static int cameraData = 0;
    Bitmap bmp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.photo_activity);
        initialize();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        // TODO Auto-generated method stub
        super.onConfigurationChanged(newConfig);
        setContentView(R.layout.photo_activity);
        initialize();
    }

    private void initialize() {
        iv = (ImageView)findViewById(R.id.imageViewReturnedPicture);
        ib = (ImageButton)findViewById(R.id.imageButtonTakePicture);
        b = (Button)findViewById(R.id.buttonSetWallpaper);
        b.setOnClickListener(this);
        ib.setOnClickListener(this);
    }

    @Override
    public void onClick(View arg0) {
        switch (arg0.getId()) {

        case R.id.buttonSetWallpaper:
            try {
                WallpaperManager wm = WallpaperManager.getInstance(getApplicationContext());
                wm.setBitmap(bmp);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            break;

        case R.id.imageButtonTakePicture:
            i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(i, cameraData);
            break;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // TODO Auto-generated method stub
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            Bundle extras = data.getExtras();
            bmp = (Bitmap)extras.get("data");
            iv.setImageBitmap(bmp);
        }
    }
}

这里就是我在清单这项活动:

                android:name="com.example.testapp.CameraActivity"
                android:label="Camera Activity"
                android:configChanges="orientation"
                android:screenOrientation="portrait" 

我已经做了相当多的搜索,但大部分是在我发现没有具体的例子。 我需要知道的代码是什么样子,而不仅是功能来使用。

我的手机是LG电子的运动。 有没有其他人遇到这个问题? 怎样才可以解决吗?

Answer 1:

在清单中,在每一个活动我用configChanges:

 <activity
        android:name=".MainActivity"
        android:configChanges="screenLayout|orientation|screenSize">

我希望这可以帮助您。



Answer 2:

你必须重写onRetainNonConfigurationInstance和使用getLastNonConfigurationInstance保存/恢复的位图。

像这样:

// during onCreate(Bundle), after initialise()
bmp = getLastNonConfigurationInstance();
if(bmp!=null){ iv.setImageBitmap(bmp); }
else { /* the image was not taken yet */ }

然后在你的活动ü覆盖:

@Override
public Object onRetainNonConfigurationInstance (){
     return bmp;
}

旋转的过程中,将“保存”的位图。

编辑:

例如,使用的onSaveInstanceState建议,将工作,但不可取的,因为它会使用大量的内存和很慢 ,但你很快就会需要其他情况:

public class SomethingSomething extends Activity{

    String name="";
    int page=0;

    // This is called when the activity is been created
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

            // if you saved something on outState you can recover them here
            if(savedInstanceState!=null){
                name = savedInstanceState.getString("name");
                page = savedInstanceState.getInt("page");
            }
    }

    // This is called before the activity is destroyed
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

            outState.putString("name", name);
            outState.putInt("page", page);
    }
}

你可以看到,这个解决方案是不适合你的情况的原因是因为Android的捆绑使用上,这是Android的特殊类型的系列化,可以处理原语,字符串和类实现Parcelable(这些类实际上只包裹他们的原语) 。 即使你做的位图实现Parcelable,它将采取了很多的时间做对的位图到包的每一个字节的副本,将被加倍位图的已大内存消耗。

现在,让我们在使用的解决方案看setRetainInstance (略低于你可以找到的例子复制\sdk\extras\android\support\samples\Support4Demos\src\com\example\android\supportv4\app\FragmentRetainInstanceSupport.Java

请务必同时检查的例子,因为它显示了一些其他花哨的技巧。

// This fragment will be managed by the framework but we won't built a UI for it.
public class FragRetained extends Fragment{
   public static final String TAG = "TAG.FragRetained";
   private Bitmap bitmap;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Tell the framework to try to keep this fragment around
        // during a configuration change.
        setRetainInstance(true);
    }
    public Bitmap getBitmap() { return bitmap; }
    public void setBitmap(Bitmap bmp) { bitmap = bmp; }
}

public class MyActivity extends Activity{

    private FragRetained myFragRetained;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
            // set the content view
            img = (ImageView)findViewById(R.id.byImgV);


            myFragRetained = getFragmentManger.findFragmentByTag(FragRetained.TAG);
            if(myFragRetained == null){
                myFragRetained = new FragRetained ();
            }else{
               Bitmap b = myFragRetained.getBitmap();
               if(b==null){
                  // the user still did not choose the photo
               }else{
                  img.setImageBitmap(b);
               }
            }
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            Bundle extras = data.getExtras();
            bmp = (Bitmap)extras.get("data");
            iv.setImageBitmap(bmp);
            myFragRetained.setBitmap(bmp);
        }
    }

}

并确保删除行android:configChanges="orientation"从你的,因为它可能做更多的伤害那么好清单 ,关于它的小报价:

注意:使用此属性,应避免使用,并仅作为最后手段。 请阅读处理有关如何正确处理重启的更多信息运行时更改由于配置更改。



Answer 3:

我去了一个移动开发小组会议上周一,并得到了暗示。 谁为一家大公司的各种平台上写应用程序的程序员提出的位图附加到应用程序对象。 当我看着我怎么可能做到这一点,我终于想出了基于以下博客文章建议,一个可行的解决方案(在后结束新的问题): http://android-er.blogspot.com/2011/ 10 /共享位图之间的活动-as.html

基本上,这些行动包含着建立位图作为终端在应用程序的任何活动都可以访问它的位置的公共资源。 我创建了一个新的类,如下所示:

package com.example.testapp;
 
import android.graphics.Bitmap;
 
public class CommonResources {
        public static Bitmap cameraBmp = null;
}

然后,我改变了所有引用的BMP CameraActivity.java到CommonResources.cameraBmp。

在初始化过程中,如果CommonResources.cameraBmp不为空,然后我用它来设置在ImageView的位图。

的onCreate现在初始化这个样子:

@Override
protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
              super.onCreate(savedInstanceState);
        setContentView(R.layout.photo_activity);
        initialize();
}

private void initialize() {
        iv = (ImageView)findViewById(R.id.imageViewReturnedPicture);
        ib = (ImageButton)findViewById(R.id.imageButtonTakePicture);
        b = (Button)findViewById(R.id.buttonSetWallpaper);
        if (CommonResources.cameraBmp != null) {
                   iv.setImageBitmap(CommonResources.cameraBmp);
           }
        b.setOnClickListener(this);
        ib.setOnClickListener(this);
}

然后,做一些清理工作,我说的onPause如下:

@Override
protected void onPause() {
        // TODO Auto-generated method stub
              super.onPause();
        if (isFinishing()) {
                   // Save the bitmap.
                        CommonResources.cameraBmp = null;
           }
}

我现在最大的问题是这样的:我有处理不当的内存或已经创建了我的垃圾收集问题?



Answer 4:

你应该处理方向改变的方式是通过保存您的实例状态。 如果您在填写的onSaveInstanceState方法,你可以得到你的onCreate中保存成捆背出来的数据。 这是为你做的意见,但其他数据,你必须拯救自己。 任何原语,parcellable,或序列化的对象可以保存这种方式,包括位图。

你应该这样做不只是为了生存配置更改,但为了保持你的状态在内存不足的情况了。



Answer 5:

在网上搜索好一阵子了简单的解决方案后,我看了一些代码,并与此来了,我希望它可以帮助人谁在未来的看法这个线程!

我有一个全局变量public Uri imageURI = null; 在我的活动类,它用于设置我使用ImaveView的图像URI; 并且在下面的代码onCreate()onSaveInstanceState()

@Override
protected void onCreate(Bundle savedInstanceState) 
{   
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_thisactivity);

    //restore the bitmap for the image
    if (savedInstanceState!=null)
    {
        imageURI=savedInstanceState.getParcelable("imageURI");
        ImageView photo=(ImageView)findViewById(R.id.image);
        photo.setImageURI(imageURI);
    }
}

@Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
    super.onSaveInstanceState(savedInstanceState);
    savedInstanceState.putParcelable("imageURI", imageURI);
}

我希望有人认为这有用的 - 只是问,如果你想了解更多详细信息。



Answer 6:

您是否尝试过加入安卓android的menifest launchMode =“singleTop”的活动,制定了我。 问题是机器人重新启动活动时,方位的变化,你的数据丢失,这个如果你的活动已经在运行它不会创建新实例。

        <activity 
            android:name=".FacebookActivity" 
            android:label="@string/facebook_app_name"
            android:launchMode="singleTop"
            android:configChanges="keyboardHidden|orientation"
            >
        </activity>


Answer 7:

无论是使用的onSaveInstanceState ,然后你通过的onCreate得到的说法,或者你会用处理取向的变化清单设置configChanges和你希望哪些情况下自己处理(例如定位|屏幕尺寸|屏幕布置)的设置。



文章来源: Android app losing data during orientation change