下面是Android Activity的工作示例代码,其中包含2个按钮,其中只有1个按钮可见:刷新按钮和停止按钮。
此代码执行以下操作:
单击刷新:启动一些AsyncTasks。任务的preExecute将隐藏刷新按钮并显示停止按钮。任务的postExecute将检查是否没有更多正在运行的任务,如果是,则显示刷新按钮并隐藏停止按钮。
单击停止:取消所有任务,显示刷新按钮并隐藏停止按钮。
此代码工作正常,但有一个例外:当我通过更改屏幕方向在任务运行时重新创建活动时。按钮现在将返回到xml中定义的状态(refresh = visibile,stop = gone)。
使用静态变量来跟踪可见性的当前状态只会使情况变得更糟,因为必须将其切换回来的正在运行的任务只能修改调用活动中的视图,该活动已被停止或销毁点!
public class MainActivity extends Activity
{
private static List<MyAsyncTask> activeTasks = new LinkedList<MyAsyncTask>();
private View refresh;
private View stop;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_main);
this.refresh = findViewById(R.id.refresh);
this.refresh.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{ // Start a couple tasks
new MyAsyncTask(MainActivity.this).execute();
new MyAsyncTask(MainActivity.this).execute();
}
});
this.stop = findViewById(R.id.stop);
this.stop.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{ // Cancel all tasks and toggle refresh button
cancelAll();
MainActivity.this.enableRefresh(true);
}
});
}
public void enableRefresh(boolean enable)
{
if (this.refresh != null && this.stop != null)
{
this.refresh.setVisibility(enable ? View.VISIBLE : View.GONE);
this.stop.setVisibility(!enable ? View.VISIBLE : View.GONE);
}
}
public static void cancelAll()
{
for (MyAsyncTask task : MainActivity.activeTasks)
task.cancel(true);
MainActivity.activeTasks = new LinkedList<MyAsyncTask>();
}
private class MyAsyncTask extends AsyncTask<Void,Void,Void>
{
private MainActivity activity;
public MyAsyncTask(MainActivity activity)
{
this.activity = activity;
}
@Override
protected void onPreExecute()
{
MainActivity.activeTasks.add(this);
this.activity.enableRefresh(false);
}
@Override
protected Void doInBackground(Void... v)
{
try
{ // Simulate a task
Thread.sleep(3000);
}
catch (InterruptedException e)
{
}
return null;
}
@Override
protected void onPostExecute(Void v)
{
MainActivity.activeTasks.remove(this);
if (MainActivity.activeTasks.size() == 0)
this.activity.enableRefresh(true);
}
}
}
答案 0 :(得分:1)
http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html
看到这一点,它将帮助你...处理方向变化中的状态
答案 1 :(得分:0)
在屏幕方向上处理AsyncTasks遵循此示例
MyAsyncTask myasynce;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
this.setContentView(R.layout.activity_main);
this.refresh = findViewById(R.id.refresh);
this.refresh.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
//Register new Task
myasynce = ( MyAsyncTask ) new MyAsyncTask(MainActivity.this).execute();
}
});
this.stop = findViewById(R.id.stop);
this.stop.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{ // Cancel all tasks and toggle refresh button
cancelAll();
MainActivity.this.enableRefresh(true);
}
});
}
现在onSaveInstanceState
添加
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//put myasynce status true if still runing false if finished
outState.putBoolean("myasynce", ( myasynce != null && query.getStatus() != AsyncTask.Status.FINISHED ) ? true : false );
if ( myasynce != null )
{
myasynce.cancel(true);
}
}
on savedInstanceState
添加
if ( savedInstanceState.getBoolean("myasynce") == true )
{
//if task was running before screen orientation run it again
myasynce = ( MyAsyncTask ) new MyAsyncTask(MainActivity.this).execute();
}
希望这个帮助
答案 2 :(得分:0)
我认为Tony Stark的这个链接http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html可能是最好的解决方案,因为这可能会解决更多问题。
但是,我认为我想出了一个更简单的解决方案来解决问题:
向MainActivity添加静态变量:
private static MainActivity current;
private static boolean enableRefresh = true;
保存enableRefresh()的输入值:
public static void enableRefresh(boolean enableRefresh)
{
MainActivity.enableRefresh = enableRefresh;
(...) // Same as before
}
添加到MainActivity onCreate():
MainActivity.current = this;
enableRefresh(enableRefresh);
在AsyncTask中,使用 MainActivity.current作为要更新的活动,而不是构造函数中提供的活动。