当我旋转设备为横向的AsyncTask的失败 [英] The AsyncTask fails when I rotate the device to landscape

查看:108
本文介绍了当我旋转设备为横向的AsyncTask的失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有,我有一个活动进度,一个的ImageView 的TextView ,我更新所有三个从的AsyncTask 当屏幕完全是一个方向的任务运行时。所有三弄更新,但的ImageView 的TextView 不显示和进度冻结时屏幕方向从一个方向切换到另一个。

添加连接分离方法的任务,并使用 retainNonConfigurationInstance 返回任务的时候活动,并使用 getLastNonConfigurationInstance 被破坏就再也没有effect.I也有为实现从的AsyncTask 获得各种进度值没有效果的三种方法。

MyActivity看起来是这样的:

 静态最后弦乐TAG =ImageUpdateActivity;
TextView的txt_currentOp;
ImageView的img_currentOp;
ImageUpdatingTask任务;
CustomProgressBar updatebar;
@燮pressWarnings(德precation)
@覆盖
保护无效的onCreate(捆绑savedInstanceState)
{
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.layout_imageupdate);
    txt_currentOp =(的TextView)findViewById(R.id.txt_currentOp);
    img_currentOp =(ImageView的)findViewById(R.id.img_updateOp);
    updatebar =(CustomProgressBar)findViewById(R.id.progressbar_update);
    字符串文件名= getIntent()getStringExtra(路径名)。
    任务=(ImageUpdatingTask)getLastNonConfigurationInstance();
    如果(任务!= NULL)
    {
        task.attach(本);
        如果(task.getStatus()== AsyncTask.Status.RUNNING)
        {
            Log.d(TAG,进度说明是:+ task.getProgressDesc());
            txt_currentOp.setText(task.getProgressDesc());
            img_currentOp.setImageBitmap(task.getProgressBitmap());
            updatebar.setProgress(task.getProgress());
        }
    }
    其他
    {
        任务=新ImageUpdatingTask(本);
        task.execute(文件名);
    }
}公共对象retainNonConfigurationInstance()
{
    task.detach();
    返回任务;
}公共布尔的onkeydown(INT键code,KeyEvent的事件){
    如果(键code == KeyEvent.KEY code_BACK&放大器;&安培; event.getRepeatCount()== 0){
        如果(task.getStatus()!= AsyncTask.Status.FINISHED)
        {
            task.cancel(真);
            任务= NULL;
        }
        意图I =新意图(这一点,图像previewActivity.class);
        startActivity(ⅰ);
    }
    返回super.onKeyDown(键code,事件);
}

这是我如何从更新的进展我的 doInBackground 方法,其中

  INT进度= 0;
 位图progressBitmap = NULL;
 字符串progressDesc = NULL;

是全局变量。

  mOperation = BITMAP_TO_PIX;
    progressDesc = getValueFromOperation(mOperation);
    PIX PIX = convertBitmapToPix(位图);
    mOperation = CONVERT_TO_8;
    progressDesc = getValueFromOperation(mOperation);
    PIX PIX2 = convertOperation(PIX);
    TEMP = pix2.copy();
    tempImg = convertPixToBitmap(临时);
    progressBitmap = tempImg;
    温度= NULL;
    进度+ = 10; // 60
    publishProgress(tempImg);

在我的 publishProgress 我使用的:

  @覆盖
保护无效onProgressUpdate(位图...值){
// TODO自动生成方法存根
    super.onProgressUpdate(值);
    INT oldOperation = 0,oldProgress = 0;
    如果(mOperation!= oldOperation)
    {
        字符串progressText = getValueFromOperation(mOperation);
        Log.d(TAG,progressText);
        activity.txt_currentOp.setText(progressText);
        oldOperation = mOperation;
    }
    如果(oldProgress!=进度)
    {
        Log.d(TAG,更新进度:+进步);
        activity.updatebar.setProgress(进度);
        oldProgress =进展情况;
    }    activity.img_currentOp.setImageBitmap(值[0]);
}

和活动,传递给使用构造的任务是:

 公共ImageUpdatingTask(ImageUpdateActivity活动)
{
    this.activity =活动;
}

这些都是采取的AsyncTask 活动之间的互动护理方法:

 公共无效连接(ImageUpdateActivity活动)
{
    this.activity =活动;
}公共无效分离()
{
    活性=无效;
}    公众诠释getProgress()
{
    返回进度;
}公共位图getProgressBitmap()
{
    返回progressBitmap;
}公共字符串getProgressDesc()
{
    返回progressDesc;
}


解决方案

在方向改变你的活动得到被破坏并重新创建。片段由活动主办。

在默认情况下,碎片被销毁,并与他们的父母,当配置发生更改时Activitys一起重建。调用片段 setRetainInstance(真)让我们绕过这个破坏和-重新创建周期,信号系统保留在活动重新片段的当前实例。

 公共无效setRetainInstance(布尔保留)在API级别11
控制的片段实例是否跨过活动重新创建保留(如从配置变化)。这只能在后面堆栈片段不被使用。如果设置,当活动被重新片段的生命周期会稍有不同:的onDestroy()将不会被调用(但onDetach()仍然是,因为碎片将被从其当前活动分离的)。
的onCreate(捆绑)将不被调用,因为没有被重新创建片段。
onAttach(活动)和onActivityCreated(束)仍将被调用。

您可以检查此博客的一种解决方法建议。使用界面回调到活动中。

http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html

和源$ C ​​$ C为同一可在

https://github.com/alexjlockwood/worker-fragments

从博客引用

活动的流程

当在MainActivity首次启动时,它实例化,并增加了TaskFragment到活动的状态。该TaskFragment创建并执行的AsyncTask和代理通过TaskCallbacks界面上的进度更新和结果返回给在MainActivity。当配置变化时,在MainActivity经过它的正常的生命周期事件,并且一旦创建了新的活动实例被传递到onAttach(活动)的方法,从而确保TaskFragment将总是即使保持到当前显示的活动实例的引用配置更改。最终的设计既简单又可靠;因为他们被推倒并重建,以及TaskFragment和它的AsyncTask永远不必担心配置更改的未predictable发生应用程序框架将处理重新分配活动的实例。

I have an Activity in which I have a ProgressBar,an ImageView and a TextView,I update all three from an AsyncTask.All three get updated when the screen is completely in one orientation when the task is running,but the ImageView and TextView are not displayed and the ProgressBar freezes when the screen orientation changes from one orientation to another.

Adding the attach and detach methods to the task and using retainNonConfigurationInstance to return the task when the Activity and using getLastNonConfigurationInstance is destroyed has had no effect.I have also implement three methods for getting the various progress values from the AsyncTask to no effect.

MyActivity looks like this:

    static final String TAG="ImageUpdateActivity";
TextView txt_currentOp;
ImageView img_currentOp;
ImageUpdatingTask task;
CustomProgressBar updatebar;
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.layout_imageupdate);
    txt_currentOp=(TextView)findViewById(R.id.txt_currentOp);
    img_currentOp=(ImageView)findViewById(R.id.img_updateOp);
    updatebar=(CustomProgressBar)findViewById(R.id.progressbar_update);
    String filename=getIntent().getStringExtra("pathName");
    task=(ImageUpdatingTask)getLastNonConfigurationInstance();
    if(task!=null)
    {
        task.attach(this);
        if(task.getStatus()==AsyncTask.Status.RUNNING)
        {   
            Log.d(TAG, "The progress description is: "+task.getProgressDesc());
            txt_currentOp.setText(task.getProgressDesc());
            img_currentOp.setImageBitmap(task.getProgressBitmap());
            updatebar.setProgress(task.getProgress());
        }
    }
    else
    {
        task=new ImageUpdatingTask(this);
        task.execute(filename);
    }
}

public Object retainNonConfigurationInstance()
{
    task.detach();
    return task;
}

public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
        if(task.getStatus()!=AsyncTask.Status.FINISHED)
        {
            task.cancel(true);
            task=null;
        }
        Intent i=new Intent(this,ImagePreviewActivity.class);
        startActivity(i);
    }
    return super.onKeyDown(keyCode, event);
}

This is how I update the progress from my doInBackground method where

 int progress=0;
 Bitmap progressBitmap=null;
 String progressDesc=null;

are global variables.

 mOperation=BITMAP_TO_PIX;
    progressDesc=getValueFromOperation(mOperation);
    Pix pix=convertBitmapToPix(bitmap);
    mOperation=CONVERT_TO_8;
    progressDesc=getValueFromOperation(mOperation);
    Pix pix2=convertOperation(pix);
    temp=pix2.copy();
    tempImg=convertPixToBitmap(temp);
    progressBitmap=tempImg;
    temp=null;
    progress+=10;//60
    publishProgress(tempImg);

And in my publishProgress I use:

   @Override
protected void onProgressUpdate(Bitmap... values) {
// TODO Auto-generated method stub
    super.onProgressUpdate(values);
    int oldOperation=0,oldProgress=0;
    if(mOperation!=oldOperation)
    {
        String progressText=getValueFromOperation(mOperation);
        Log.d(TAG, progressText);
        activity.txt_currentOp.setText(progressText);
        oldOperation=mOperation;
    }
    if(oldProgress!=progress)
    {
        Log.d(TAG,"Update the progress: "+progress);
        activity.updatebar.setProgress(progress);
        oldProgress=progress;
    }

    activity.img_currentOp.setImageBitmap(values[0]);
}

And the Activity,is passed to the task using the constructor:

  public ImageUpdatingTask(ImageUpdateActivity activity)
{
    this.activity=activity;
}

These are the methods that take care of interaction between the AsyncTask and the Activity:

   public void attach(ImageUpdateActivity activity)
{
    this.activity=activity;
}

public void detach()
{
    activity=null;
}

    public int getProgress()
{
    return progress;
}

public Bitmap getProgressBitmap()
{
    return progressBitmap;
}

public String getProgressDesc()
{
    return progressDesc;
}

解决方案

When orientation changes your activity gets is destroyed and recreated. Fragments are hosted by an activity.

By default, Fragments are destroyed and recreated along with their parent Activitys when a configuration change occurs. Calling Fragments setRetainInstance(true) allows us to bypass this destroy-and-recreate cycle, signaling the system to retain the current instance of the fragment when the activity is recreated.

public void setRetainInstance (boolean retain)

Added in API level 11
Control whether a fragment instance is retained across Activity re-creation (such as from a configuration change). This can only be used with fragments not in the back stack. If set, the fragment lifecycle will be slightly different when an activity is recreated:

onDestroy() will not be called (but onDetach() still will be, because the fragment is being detached from its current activity).
onCreate(Bundle) will not be called since the fragment is not being re-created.
onAttach(Activity) and onActivityCreated(Bundle) will still be called.

You can check this blog for a workaround suggested . Uses interface as callback to the activity.

http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html

and the source code for the same is available at

https://github.com/alexjlockwood/worker-fragments

Quoting from the blog

Flow of Events

When the MainActivity starts up for the first time, it instantiates and adds the TaskFragment to the Activity's state. The TaskFragment creates and executes an AsyncTask and proxies progress updates and results back to the MainActivity via the TaskCallbacks interface. When a configuration change occurs, the MainActivity goes through its normal lifecycle events, and once created the new Activity instance is passed to the onAttach(Activity) method, thus ensuring that the TaskFragment will always hold a reference to the currently displayed Activity instance even after the configuration change. The resulting design is both simple and reliable; the application framework will handle re-assigning Activity instances as they are torn down and recreated, and the TaskFragment and its AsyncTask never need to worry about the unpredictable occurrence of a configuration change.

这篇关于当我旋转设备为横向的AsyncTask的失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆