Skip to content

Instantly share code, notes, and snippets.

@tomoattori
Last active December 26, 2015 09:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomoattori/7131930 to your computer and use it in GitHub Desktop.
Save tomoattori/7131930 to your computer and use it in GitHub Desktop.
ProgressDialogからキャンセル可能なAsyncTask(未完成)
// ・AsyncTaskで処理を実行
// ・ProgressDialogで進行状況を表示
// ・途中キャンセル可能
//
// という実装をしたいのだけどどうにもうまく行ってないコード。
// (普通に使う分には問題ないけどonPause時に例外を吐いて落ちる)
package com.example.cancelasyncprogress;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import android.app.Activity;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import java.io.Serializable;
public class MainActivity extends Activity {
Activity activity = this;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// タスクを実行するボタンを定義
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// AsyncTaskの実行
CancellableAsyncTask task = new CancellableAsyncTask();
task.execute();
}
});
}
// ProgressDialogを出しつつキャンセル可能なAsyncTask(目標)
public class CancellableAsyncTask extends AsyncTask<Void, Integer, Boolean> {
private ProcessingDialog dialog;
@Override
protected void onPreExecute() {
// ProgressDialogに設定するパラメータの設定
Bundle argsD = new Bundle();
argsD.putString("title", "実行中");
argsD.putString("message", "しばらくお待ちください");
argsD.putSerializable("listener", new ProcessingDialog.CancelListener() {
private static final long serialVersionUID = 1L;
@Override
public void canceled(DialogInterface _interface) {
Toast.makeText(activity, "タスクをキャンセルします", Toast.LENGTH_SHORT).show();
// BACKキーでDialogを消す際にTaskを停止。
cancel(true);
}
});
// ProgressDialogを表示する
dialog = new ProcessingDialog();
dialog.setArguments(argsD);
dialog.show(activity.getFragmentManager(), "setdata");
}
@Override
protected Boolean doInBackground(Void... args) {
// 1秒ごとにProgressDialogを更新するだけの簡単なお仕事
int count = 0;
while (count < 10) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
publishProgress(++count);
}
return true;
}
@Override
protected void onProgressUpdate(Integer... values) {
dialog.updateProgress(values[0]);
}
@Override
protected void onPostExecute(Boolean result) {
dialog.getDialog().dismiss();
Toast.makeText(activity, "タスクが終了しました", Toast.LENGTH_SHORT).show();
}
@Override
protected void onCancelled() {
Toast.makeText(activity, "キャンセルされました", Toast.LENGTH_SHORT).show();
}
}
// AsyncTaskから生成されるProgressDialog(を生成するDialogFragment)
public static class ProcessingDialog extends DialogFragment {
// キャンセルリスナー用インターフェースの定義
public interface CancelListener extends Serializable {
public void canceled(DialogInterface di);
}
// Bundleで渡されるリスナーの保管場所
private CancelListener listener = null;
// ProgressDialog本体
private ProgressDialog progressDialog;
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Bundleからリスナーを取得
listener = (CancelListener) getArguments().getSerializable("listener");
// ダイアログが生成ずみの場合はそれを返す
if (progressDialog != null) {
return progressDialog;
}
// ダイアログをキャンセル可能にする
setCancelable(true);
// ダイアログを生成する
progressDialog = new ProgressDialog(getActivity());
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setTitle(getArguments().getString("title"));
progressDialog.setMessage(getArguments().getString("message"));
progressDialog.setMax(10);
return progressDialog;
}
// キャンセルリスナーの実装(?)
@Override
public void onCancel(DialogInterface di) {
listener.canceled(di);
}
// プログレスバーの更新
public void updateProgress(int value) {
if (progressDialog != null) {
progressDialog.setProgress(value);
}
}
@Override
public void onDestroy() {
super.onDestroy();
progressDialog = null;
}
}
}
E/AndroidRuntime( 9211): FATAL EXCEPTION: main
E/AndroidRuntime( 9211): java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = com.example.cancelasyncprogress.MainActivity$CancellableAsyncTask$1)
E/AndroidRuntime( 9211): at android.os.Parcel.writeSerializable(Parcel.java:1279)
E/AndroidRuntime( 9211): at android.os.Parcel.writeValue(Parcel.java:1233)
E/AndroidRuntime( 9211): at android.os.Parcel.writeMapInternal(Parcel.java:591)
E/AndroidRuntime( 9211): at android.os.Bundle.writeToParcel(Bundle.java:1627)
E/AndroidRuntime( 9211): at android.os.Parcel.writeBundle(Parcel.java:605)
E/AndroidRuntime( 9211): at android.app.FragmentState.writeToParcel(Fragment.java:131)
E/AndroidRuntime( 9211): at android.os.Parcel.writeTypedArray(Parcel.java:1102)
E/AndroidRuntime( 9211): at android.app.FragmentManagerState.writeToParcel(FragmentManager.java:371)
E/AndroidRuntime( 9211): at android.os.Parcel.writeParcelable(Parcel.java:1254)
E/AndroidRuntime( 9211): at android.os.Parcel.writeValue(Parcel.java:1173)
E/AndroidRuntime( 9211): at android.os.Parcel.writeMapInternal(Parcel.java:591)
E/AndroidRuntime( 9211): at android.os.Bundle.writeToParcel(Bundle.java:1627)
E/AndroidRuntime( 9211): at android.os.Parcel.writeBundle(Parcel.java:605)
E/AndroidRuntime( 9211): at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:2252)
E/AndroidRuntime( 9211): at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3052)
E/AndroidRuntime( 9211): at android.os.Handler.handleCallback(Handler.java:725)
E/AndroidRuntime( 9211): at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime( 9211): at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime( 9211): at android.app.ActivityThread.main(ActivityThread.java:5041)
E/AndroidRuntime( 9211): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 9211): at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime( 9211): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
E/AndroidRuntime( 9211): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
E/AndroidRuntime( 9211): at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 9211): Caused by: java.io.NotSerializableException: com.example.cancelasyncprogress.MainActivity$CancellableAsyncTask
E/AndroidRuntime( 9211): at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1364)
E/AndroidRuntime( 9211): at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
E/AndroidRuntime( 9211): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
E/AndroidRuntime( 9211): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
E/AndroidRuntime( 9211): at java.io.ObjectOutputStream.writeFieldValues(ObjectOutputStream.java:979)
E/AndroidRuntime( 9211): at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:368)
E/AndroidRuntime( 9211): at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1074)
E/AndroidRuntime( 9211): at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1404)
E/AndroidRuntime( 9211): at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1671)
E/AndroidRuntime( 9211): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1517)
E/AndroidRuntime( 9211): at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
E/AndroidRuntime( 9211): at android.os.Parcel.writeSerializable(Parcel.java:1274)
E/AndroidRuntime( 9211): ... 23 more
W/ActivityManager( 391): Force finishing activity com.example.cancelasyncprogress/.MainActivity
@tomoattori
Copy link
Author

知識の元ネタは以下のサイト。(ありがとうございます)

AsyncTaskと仲良くなろう:バックグラウンド処理とキャンセル - ReDo
http://greety.sakura.ne.jp/redo/2011/02/asynctask.html

画面回転、キャンセル対応のProgress DialogFragment-Oboe吹きプログラマの黙示録
http://blog.zaq.ne.jp/oboe2uran/article/877/

@tomoattori
Copy link
Author

putSerializableしたオブジェクトのonPause越えはヤバイ、なんて情報も見つかるのですが、この辺関係あるのかしら?

Bundle の putSerializable() で List や Map や CharSequence を実装したオブジェクトを渡すのはやばい - gae+eyoの日記
http://d.hatena.ne.jp/gae+eyo/20130801/1375339519

画面の向きを変えたりとか - らくがき
http://www.wildtree.jp/~araki/rakugaki/2011/05/post-2431.html

@tomoattori
Copy link
Author

たまたま同じようなことを考えていたmstsskさんの実装。
これがonPauseを越えられたのかどうかちょっと気になる。

FragmentからActivityにコールバックする手段の一つとして、listenerをserializableにしてargmentsに詰めてしまうやり方を試してみた。
https://gist.github.com/mstssk/7123411

@tomoattori
Copy link
Author

相手がActivityなコールバックの場合はyanzm先生の実装が一番いいみたいなのですが、今回やりたい事(AsyncTaskのキャンセル)にも応用できるのかしら?

Y.A.M の 雑記帳: Fragment から Activity にコールバックする方法
http://y-anz-m.blogspot.jp/2012/06/fragment-activity.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment