Android 异步任务与方向的变化
在更改屏幕方向时,我遇到了重新创建活动、进度对话框和异步任务的问题。我在这里看到了一些解决方案,并决定使用onRetainStatonConfiguration()保存AsyncTask的实例。在onCreate中,我检查是否有AsyncTask的实例,如果存在,我将显示一个新的进度对话框。但是这个对话框将UI阻塞在无限循环中(在onPostExecute中有dialog.disease()),当然活动不会显示结果 onCreateAndroid 异步任务与方向的变化,android,android-asynctask,progressdialog,screen-orientation,Android,Android Asynctask,Progressdialog,Screen Orientation,在更改屏幕方向时,我遇到了重新创建活动、进度对话框和异步任务的问题。我在这里看到了一些解决方案,并决定使用onRetainStatonConfiguration()保存AsyncTask的实例。在onCreate中,我检查是否有AsyncTask的实例,如果存在,我将显示一个新的进度对话框。但是这个对话框将UI阻塞在无限循环中(在onPostExecute中有dialog.disease()),当然活动不会显示结果 onCreate getDirection=(getDirection)getL
getDirection=(getDirection)getLastCustomNonConfigurationInstance();
if(getDirection!=null){
dialog=新建ProgressDialog(RouteActivity.this);
setMessage(getResources().getString(R.string.loading_data));
dialog.setUndeterminate(false);
对话框。可设置可取消(false);
dialog.show();
}否则{
getDirection=新的getDirection();
getDirection.execute();
}
重新设置为非配置状态
@覆盖
公共对象OnRetainCustomOnConfiguration安装(){
返回方向;
}
@凌驾
受保护的空onDestroy(){
super.ondestory();
if(dialog.isShowing()){
dialog.dismise();
}
}
编辑#1:
我采用了带有片段和保留片段的翠鸟解决方案,但当我在AsyncTask的doInBackground期间更改方向时,可扩展Listview上会出现NPE
08-14 12:50:40.866:E/AndroidRuntime(22739):致命异常:主
08-14 12:50:40.866:E/AndroidRuntime(22739):java.lang.NullPointerException
08-14 12:50:40.866:E/AndroidRuntime(22739):位于com.pasquini.adapter.ListRouteExpandableAdapter.getGroupCount(ListRouteExpandableAdapter.java:78)
08-14 12:50:40.866:E/AndroidRuntime(22739):位于android.widget.ExpandableListConnector.getCount(ExpandableListConnector.java:399)
08-14 12:50:40.866:E/AndroidRuntime(22739):位于android.widget.ListView.setAdapter(ListView.java:460)
08-14 12:50:40.866:E/AndroidRuntime(22739):位于android.widget.ExpandableListView.setAdapter(ExpandableListView.java:470)
08-14 12:50:40.866:E/AndroidRuntime(22739):位于com.pasquini.activity.RouteActivity.onPostExecute(RouteActivity.java:792)
08-14 12:50:40.866:E/AndroidRuntime(22739):位于com.pasquini.fragment.GetDirectionFragment$GetDirectionTask.onPostExecute(GetDirectionFragment.java:244)
08-14 12:50:40.866:E/AndroidRuntime(22739):位于com.pasquini.fragment.GetDirectionFragment$GetDirectionTask.onPostExecute(GetDirectionFragment.java:1)
08-14 12:50:40.866:E/AndroidRuntime(22739):在android.os.AsyncTask.finish(AsyncTask.java:631)
08-14 12:50:40.866:E/AndroidRuntime(22739):在android.os.AsyncTask.access$600(AsyncTask.java:177)
08-14 12:50:40.866:E/AndroidRuntime(22739):位于android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
08-14 12:50:40.866:E/AndroidRuntime(22739):在android.os.Handler.dispatchMessage(Handler.java:99)上
08-14 12:50:40.866:E/AndroidRuntime(22739):在android.os.Looper.loop(Looper.java:137)上
08-14 12:50:40.866:E/AndroidRuntime(22739):位于android.app.ActivityThread.main(ActivityThread.java:4895)
08-14 12:50:40.866:E/AndroidRuntime(22739):位于java.lang.reflect.Method.Invokenactive(本机方法)
08-14 12:50:40.866:E/AndroidRuntime(22739):位于java.lang.reflect.Method.invoke(Method.java:511)
08-14 12:50:40.866:E/AndroidRuntime(22739):在com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:994)
08-14 12:50:40.866:E/AndroidRuntime(22739):位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:761)
8-14 12:50:40.866:E/AndroidRuntime(22739):在dalvik.system.NativeStart.main(本机方法)。
这里是代码片段:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.add(R.id.container, new MainFragment());
transaction.commit();
}
}
}
public class MainFragment extends Fragment implements View.OnClickListener, SampleAsyncTask.Callback {
private Button mExecuteButton;
private ProgressDialog mProgressDialog;
@Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
mExecuteButton = (Button) view.findViewById(R.id.execute_button);
mExecuteButton.setOnClickListener(this);
SampleAsyncTask asyncTask = SampleAsyncTask.Holder.Instance.get();
asyncTask.setCallback(this);
if (asyncTask.isRunning()) {
showProgressDialog(asyncTask.getProgress());
}
return view;
}
@Override
public void onDetach () {
SampleAsyncTask asyncTask = SampleAsyncTask.Holder.Instance.get();
if (asyncTask.isRunning()) {
asyncTask.setCallback(null);
}
if (mProgressDialog != null) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
super.onDetach();
}
private void showProgressDialog (int progress) {
mProgressDialog = new ProgressDialog(getActivity());
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setButton(ProgressDialog.BUTTON_NEGATIVE, "Cancel", makeNegativeButtonListener());
mProgressDialog.setCancelable(false);
mProgressDialog.setProgress(progress);
mProgressDialog.setMax(100);
mProgressDialog.show();
}
private DialogInterface.OnClickListener makeNegativeButtonListener () {
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
@Override
public void onClick (DialogInterface dialog, int which) {
SampleAsyncTask asyncTask = SampleAsyncTask.Holder.Instance.get();
if (asyncTask.isRunning()) {
asyncTask.cancel(true);
mProgressDialog.dismiss();
}
}
};
return listener;
}
@Override
public void onClick (View v) {
SampleAsyncTask asyncTask = SampleAsyncTask.Holder.Instance.get();
asyncTask.setCallback(this);
if (!asyncTask.isRunning()) {
showProgressDialog(0);
asyncTask.execute(100, 200);
}
}
// SampleAsyncTask.Callback implementation
@Override
public void onPostExecute (boolean success) {
String message = (success) ? "SUCCESS" : "FAIL";
Toast.makeText(getActivity(), message, Toast.LENGTH_SHORT).show();
mProgressDialog.dismiss();
}
@Override
public void onProgressUpdate (int progressValue) {
if (mProgressDialog != null) {
mProgressDialog.setProgress(progressValue);
}
}
}
public class SampleAsyncTask extends AsyncTask<Integer, Integer, Boolean> {
public static final String LOG_TAG = SampleAsyncTask.class.getSimpleName();
private static final Callback LOG_CALLBACK = new Callback() {
@Override
public void onPostExecute (boolean success) {
Log.i(LOG_TAG, "#onPostExecute (" + success + ")");
}
@Override
public void onProgressUpdate (int progressValue) {
Log.i(LOG_TAG, "#onProgressUpdate(" + progressValue + ")");
}
};
private boolean mRunning = false;
private int mProgress = -1;
private Callback mCallback = LOG_CALLBACK;
public void setCallback (Callback callback) {
if (callback == null) {
mCallback = LOG_CALLBACK;
}
else {
mCallback = callback;
}
}
public boolean isRunning () {
return mRunning;
}
public int getProgress () {
return mProgress;
}
@Override
protected Boolean doInBackground (Integer... params) {
mRunning = true;
for (int i = 0; i < params[0]; i++) {
if (isCancelled()) {
return false;
}
try {
Thread.sleep(params[1]);
mProgress = i;
publishProgress(i);
}
catch (InterruptedException e) {
return false;
}
}
return true;
}
@Override
protected void onPostExecute (Boolean success) {
mRunning = false;
Holder.Instance.reset();
mCallback.onPostExecute(success);
}
@Override
protected void onProgressUpdate (Integer... values) {
mCallback.onProgressUpdate(values[0]);
}
@Override
protected void onCancelled (Boolean aBoolean) {
mRunning = false;
Holder.Instance.reset();
}
@Override
protected void onCancelled () {
mRunning = false;
Holder.Instance.reset();
}
public enum Holder {
Instance;
private SampleAsyncTask mSampleAsyncTask;
public SampleAsyncTask get () {
if (mSampleAsyncTask == null) {
mSampleAsyncTask = new SampleAsyncTask();
}
return mSampleAsyncTask;
}
private void reset () {
mSampleAsyncTask = null;
}
}
public interface Callback {
public void onPostExecute (boolean success);
public void onProgressUpdate (int progressValue);
}
}
公共类GetDirectionFragment扩展了片段{
私人地图立法会;
私人ArrayList legsAndSteps;
私人名单;
私人名单;
私人名单polyz;
/**
*回调接口,片段将通过该接口报告
*任务的进度和结果返回到活动。
*/
公共静态接口任务回调{
void onPreExecute();
void onPostExecute();
列出GetListPoiberRoute();
void setLegs(列出legs、映射legsCollection);
void setPolyline(列表polyz);
}
私有任务回调回调;
私有GetDirectionTask GetDirectionTask;
/**
*保留对父活动的引用,以便我们可以报告
*任务的当前进度和结果。Android框架
*将在之后向我们传递对新创建活动的引用
*每次配置更改。
*/
@凌驾
公共事务主任(活动){
超级转速计(活动);
试一试{
回调=(TaskCallbacks)活动;
}catch(ClassCastException e){
抛出新的ClassCastException(activity.toString()+“必须实现TaskCallbacks”);
}
pois=callbacks.getListPoiberRoute();
}
/**
*此方法仅在保留
*首先创建片段。
*/
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//跨配置更改保留此片段。
setRetainInstance(真);
//创建并执行后台任务。
getDirectionTask=新建getDirectionTask();
getDirectionTask.execute();
}
/**
*将回调设置为null,这样我们就不会意外泄漏
*活动实例。
*/
@凌驾
公共无效连接(){
super.onDetach();
回调=null;
}
私有类GetDirectionTask扩展了AsyncTask{
@凌驾
受保护的void onPreExecute(){
if(回调!=null){
callbacks.onPreExecute();
}
}
/**
*注意,我们不调用回调对象的方法
*直接从后台线程,因为这可能导致
*处于比赛状态。
*/
public class SampleAsyncTask extends AsyncTask<Integer, Integer, Boolean> {
public static final String LOG_TAG = SampleAsyncTask.class.getSimpleName();
private static final Callback LOG_CALLBACK = new Callback() {
@Override
public void onPostExecute (boolean success) {
Log.i(LOG_TAG, "#onPostExecute (" + success + ")");
}
@Override
public void onProgressUpdate (int progressValue) {
Log.i(LOG_TAG, "#onProgressUpdate(" + progressValue + ")");
}
};
private boolean mRunning = false;
private int mProgress = -1;
private Callback mCallback = LOG_CALLBACK;
public void setCallback (Callback callback) {
if (callback == null) {
mCallback = LOG_CALLBACK;
}
else {
mCallback = callback;
}
}
public boolean isRunning () {
return mRunning;
}
public int getProgress () {
return mProgress;
}
@Override
protected Boolean doInBackground (Integer... params) {
mRunning = true;
for (int i = 0; i < params[0]; i++) {
if (isCancelled()) {
return false;
}
try {
Thread.sleep(params[1]);
mProgress = i;
publishProgress(i);
}
catch (InterruptedException e) {
return false;
}
}
return true;
}
@Override
protected void onPostExecute (Boolean success) {
mRunning = false;
Holder.Instance.reset();
mCallback.onPostExecute(success);
}
@Override
protected void onProgressUpdate (Integer... values) {
mCallback.onProgressUpdate(values[0]);
}
@Override
protected void onCancelled (Boolean aBoolean) {
mRunning = false;
Holder.Instance.reset();
}
@Override
protected void onCancelled () {
mRunning = false;
Holder.Instance.reset();
}
public enum Holder {
Instance;
private SampleAsyncTask mSampleAsyncTask;
public SampleAsyncTask get () {
if (mSampleAsyncTask == null) {
mSampleAsyncTask = new SampleAsyncTask();
}
return mSampleAsyncTask;
}
private void reset () {
mSampleAsyncTask = null;
}
}
public interface Callback {
public void onPostExecute (boolean success);
public void onProgressUpdate (int progressValue);
}
}
public class TheApp extends Application {
private static TheApp sTheApp;
private HashMap<String, AsyncTask<?,?,?>> tasks = new HashMap<String, AsyncTask<?,?,?>>();
@Override
public void onCreate() {
super.onCreate();
sTheApp = this;
}
public static TheApp get() {
return sTheApp;
}
public void registerTask(String tag, AsyncTask<?,?,?> task) {
tasks.put(tag, task);
}
public void unregisterTask(String tag) {
tasks.remove(tag);
}
public AsyncTask<?,?,?> getTask(String tag) {
return tasks.get(tag);
}
}
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:name="com.example.tasktest.TheApp">
public class MainActivity extends Activity {
private Task1 mTask1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTask1 = (Task1)TheApp.get().getTask("task1");
}
/*
* start task is not running jet
*/
public void handletask1(View v) {
if (mTask1 == null) {
mTask1 = new Task1();
TheApp.get().registerTask("task1", mTask1);
mTask1.execute();
} else
Toast.makeText(this, "Task is running...", Toast.LENGTH_SHORT).show();
}
/*
* cancel task if is not finished
*/
public void handelCancel(View v) {
if (mTask1 != null)
mTask1.cancel(false);
}
public class Task1 extends AsyncTask<Void, Void, Void>{
@Override
protected Void doInBackground(Void... params) {
try {
for(int i=0; i<120; i++) {
Thread.sleep(1000);
Log.i("tests", "loop=" + i);
if (this.isCancelled()) {
Log.e("tests", "tssk cancelled");
break;
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onCancelled(Void result) {
TheApp.get().unregisterTask("task1");
mTask1 = null;
}
@Override
protected void onPostExecute(Void result) {
TheApp.get().unregisterTask("task1");
mTask1 = null;
}
}
}