質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

1回答

9170閲覧

【Android】非同期処理後にページ遷移をしたい

GH_usami13

総合スコア24

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

1クリップ

投稿2015/10/02 08:54

編集2015/10/06 18:05

【10月6日質問編集】

おこなっていることは、
dialogfragmentでonClickをすると非同期処理をおこない、
非同期処理が終了したら
Activityの遷移をおこなっております。

しかし、fragmentで非同期処理をおこなうと、
Activityとの接続が切れて
新たなActivityを呼ぼうとした時に
getActivityがnullになってしまい、
遷移できずにエラーになってしまいます。

dialogfragmentで処理しているコードが下記になります。

java

1public class AnnotationDialogFragment extends DialogFragment { 2 3 public String name; 4 public String snippet; 5 Context context; 6 7 @Override 8 public Dialog onCreateDialog(Bundle savedInstanceState) { 9 10 int index = snippet.indexOf(":"); 11 final String id = snippet.substring(0, index); 12 snippet = snippet.substring(index + 1); 13 14 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 15 builder.setTitle(name); 16 builder.setMessage(snippet); 17 builder.setPositiveButton(R.string.detail, new DialogInterface.OnClickListener() { 18 @Override 19 public void onClick(final DialogInterface dialog, int which) { 20 AsyncDetail asyncDetail = new AsyncDetail(new AsyncTaskCallback() { 21 @Override 22 public void postExecute(String result) { //この時点でgetActivityはnull 23 Intent intent = new Intent(getActivity() , DetailActivity.class); 24 intent.setClassName("パッケージ名", "パッケージ名.DetailActivity"); 25 intent.putExtra("result", result); 26 startActivity(intent); 27 } 28 } ); 29 asyncDetail.execute("URL", id); 30 } 31 }); 32 builder.setNegativeButton(R.string.close, new DialogInterface.OnClickListener() { 33 @Override 34 public void onClick(DialogInterface dialog, int which) { 35 // TODO Auto-generated method stub 36 } 37 }); 38 return builder.create(); 39 }

非同期処理をおこなうAsyncTaskを継承したクラスが下記になります。

java

1public class AsyncDetail extends AsyncTask<String, Integer, String> { 2 3 public AsyncTaskCallback callback = null; 4 5 public AsyncDetail(AsyncTaskCallback _callback) { 6 this.callback = _callback; 7 } 8 9 private HttpClient hClient = new DefaultHttpClient(); 10 11 // バックグラウンドで処理 12 @Override 13 protected String doInBackground(String... params) { 14 String uri = params[0]; 15 int id = Integer.parseInt( params[1] ); 16 return PostLocations(uri, id); 17 } 18 19 // バックグラウンド処理が終了した後にメインスレッドに渡す処理 20 protected void onPostExecute(String result) { 21 super.onPostExecute(result); 22 this.callback.postExecute(result); 23 } 24 25 // 位置情報(JSON)をダウンロード 26 private String PostLocations(String uri, int id) { 27 try { 28 HttpPost post = new HttpPost(uri); 29 JSONObject jsonObject = new JSONObject(); 30 jsonObject.put("id", id); 31 StringEntity se = new StringEntity(jsonObject.toString(), "UTF-8"); 32 post.setHeader("Accept", "application/json"); 33 post.setHeader("Content-Type", "application/json"); 34 post.setEntity(se); 35 HttpResponse resp = hClient.execute(post); 36 37 if (resp.getStatusLine().getStatusCode() < 400) { 38 String str = EntityUtils.toString(resp.getEntity(), HTTP.UTF_8); 39 return str; 40 } 41 } catch (Exception e) { 42 e.printStackTrace(); 43 } 44 return null; 45 } 46 47}

コールバックインターフェースを下記に記します。

public interface AsyncTaskCallback { void postExecute(String result); }

非同期処理をさせてもActivityを保持させていられるやり方か、
新たにActivityを生成させるやり方を知りたいです。

また、これらの書き方はよくないということでありましたら、
どんな方法が良いのかお教えいただけますと幸いです。

皆様のお力添えのほど、よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

遷移後のアクティビティを呼び出せていないから起こる

コードを見るに、遷移先のアクティビティは関係ないと思います。

例外が発生しているのはAsyncDetailの以下の部分です。

Java

1protected void onPreExecute() { 2 super.onPreExecute(); 3 this.callback.preExecute(); // ココ 4}

エラー内容は、このcallbacknullだったため、preExecuteを実行できなかった、という意味です。

理由は上記の通りですが、何故nullなのかは

Java

1public void onClick(DialogInterface dialog, int which) { 2 AsyncDetail asyncTask = new AsyncDetail(this); 3 asyncTask.execute("URL", id); 4 getActivity().finish(); 5}

Java

1public AsyncDetail(android.content.DialogInterface.OnClickListener onClickListener) { 2 // TODO Auto-generated constructor stub 3 hClient = new DefaultHttpClient(); 4}

この2つの部分に原因があると思われます。

上の部分で、new AsyncDetail(this);と記述していますが、このthisAsyncTaskCallbackを実装していますか?
恐らく実装していないのではないでしょうか?
しかし、下の部分のコンストラクタがあるためコンパイルエラーにはならず、結果、ビルドはできる状態になったのだと思います。


そもそも、

ダイアログでonClickすることで非同期処理をおこない、
非同期処理が終了したら、
新たなアクティビティで処理後の内容を出力したいです。

この目的とコードがチグハグです。
質問文のコードでは、遷移前と遷移後、どちらでも非同期処理を行おうとしています。

遷移前に、非同期処理を行い、非同期処理が終了したら遷移。

Java

1@Override 2public void onClick(DialogInterface dialog, int which) { 3 AsyncDetail asyncTask = new AsyncDetail(new AsyncTaskCallback() { 4 public void postExecute(String result) { 5 Intent intent = new Intent(getApplicationContext(), DetailActivity.class); 6 intent.putExtra("RESULT", result); 7 startActivity(intent); 8 } 9 // 他 略 10 }); 11 asyncTask.execute("URL", id); 12 getActivity().finish(); 13}

遷移後にデータを表示。

Java

1public class DetailActivity extends Activity { 2 protected void onCreate(Bundle savedInstanceState) { 3 super.onCreate(savedInstanceState); 4 setContentView(R.layout.activity_detail); 5 6 Intent intent = getIntent(); 7 String result = intent.getStringExtra("RESULT"); 8 // 出力処理など 9 } 10}

目的にそうとしたら、大まかなコードですが、こんな感じになるのではないでしょうか。

AsyncDetailにも怪しいコードがありますが、質問内容とは離れるため、ひとまずはノータッチです。すいません。


2015/10/4 追記
例外のスタックトレースが無いので、推測になってしまいますが、原因は以下の部分かもしれません。

Java

1public void onClick(DialogInterface dialog, int which) { 2 AsyncDetail asyncDetail = new AsyncDetail(new AsyncTaskCallback() { 3 @Override 4 public void postExecute(String result) { 5 Intent intent = new Intent(getActivity(), DetailActivity.class); // ココ 6 intent.putExtra("result", result); 7 startActivity(intent); 8 } 9 }); 10 getActivity().finish(); // ココ 11 asyncDetail.execute("URL", id); 12}

非同期処理開始前に、Activityをfinishしているのに、非同期処理完了時に、getActivity()でActivityを取得しようとしています。
getActivity().finish();を非同期処理完了時に実行するか、別の方法でContextを取得してみてください。


Fragmentのコードを確認したところ、Fragment#startActivity(Intent)はFragment自身が設置されているActivityのActivity#startActivity()を呼ぶような処理をしています。
なので、Fragment#startActivity(Intent)を呼ぶ前に、設置されているActivityのAcitivity#finish()呼んでしまった場合、Activity#startActivity()が呼び出せなくなるのだと思います。
実際のソースコードでは呼ぶ前にnullチェックをしており、nullの場合に件の例外を投げるようになっていました。

ですので、上に書いたように、getActivity().finish();を非同期処理完了時に実行するのがいいと思います。


getActivity().finish();postExecute内に移してみてください。

Java

1public void onClick(DialogInterface dialog, int which) { 2 AsyncDetail asyncDetail = new AsyncDetail(new AsyncTaskCallback() { 3 @Override 4 public void postExecute(String result) { 5 Intent intent = new Intent(getActivity(), DetailActivity.class); 6 intent.putExtra("result", result); 7 startActivity(intent); 8 getActivity().finish(); // ここに移す 9 } 10 }); 11 // getActivity().finish(); 12 asyncDetail.execute("URL", id); 13}

投稿2015/10/02 10:10

編集2015/10/07 07:19
shiolier

総合スコア1156

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

GH_usami13

2015/10/04 09:43

ご回答有り難うございます。 half_sleepingさんのおっしゃられるように 認識がだいぶおかしかったようです。 改めて、コードを改変して色々と実行してみたのですが、 違ったエラーで苦戦してしまいました。 よろしければご教授のほど、 よろしくお願いいたします。
GH_usami13

2015/10/04 12:31 編集

追加の回答ありがとうございます。 もうしわけございません。 元のコードに少々誤りがございました。 Intentのインスタンスを生成するときに contextを第一引数としていましたが、 Contextの生成のコードを載せておりませんでした。 @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setPositiveButton(R.string.detail, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { AsyncDetail asyncDetail = new AsyncDetail(new AsyncTaskCallback() { @Override public void postExecute(String result) { Intent intent = new Intent(context , DetailActivity.class); intent.putExtra("result", result); startActivity(intent); } }); getActivity().finish(); asyncDetail.execute("URL", id); } }) return builder.create(); } //ここを書き忘れておりました @Override public void onAttach(Activity activity){ super.onAttach(activity); context = activity; } また、スタックトレースは以下のようになっております。 java.lang.IllegalStateException: Fragment AnnotationDialogFragment{206bef1d} not attached to Activity W/System.err﹕ at android.app.Fragment.startActivity(Fragment.java:1068) W/System.err﹕ at android.app.Fragment.startActivity(Fragment.java:1054) W/System.err﹕ at パッケージ名.AnnotationDialogFragment$2$1.postExecute(AnnotationDialogFragment.java:41) //startActivity(intent) W/System.err﹕ at パッケージ名.AsyncDetail.onPostExecute(AsyncDetail.java:36) W/System.err﹕ at パッケージ名.AsyncDetail.onPostExecute(AsyncDetail.java:15) W/System.err﹕ at android.os.AsyncTask.finish(AsyncTask.java:636) W/System.err﹕ at android.os.AsyncTask.access$500(AsyncTask.java:177) W/System.err﹕ at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:653) W/System.err﹕ at android.os.Handler.dispatchMessage(Handler.java:102) 10-04 21:17:23.422 2701-2701/com.example.mac_gusami.pr_sample0917 W/System.err﹕ at android.os.Looper.loop(Looper.java:135) W/System.err﹕ at android.app.ActivityThread.main(ActivityThread.java:5254) W/System.err﹕ at java.lang.reflect.Method.invoke(Native Method) W/System.err﹕ at java.lang.reflect.Method.invoke(Method.java:372) W/System.err﹕ at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) W/System.err﹕ at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) デバッグをしてみても、 contextにMapsActivityが格納されており、 MapsActivityからDetailActivityに遷移するという認識です。 よろしくお願いいたします。
GH_usami13

2015/10/06 17:51

ご丁寧に解説していただきありがとうございます。 非同期処理をおこなった瞬間、FragmantとActivityとの接続が切れてしまって、 非同期処理後にActivityを呼ぼうと思っても、 getActivity()がnullになってしまい、 前回のコメントで記載したようなエラーになってしまうようですね。 どうにかActivityを保持させて非同期処理後にそのActivityから新しいActivity(DetailActivity)へ遷移できないものかと調べてはいるのですが、 half_sleepingさんがおっしゃられるように、 非同期処理後にgetActivity().finish();おこなう方法がわかりませんでした。 大変ご迷惑おかけしますが、 もう少し具体的にお教えいただくことは可能でしょうか? また、他の方法をとった方がよろしいのでしょうか? (例)AsyncTaskLoader 何卒よろしくお願いいたします。
GH_usami13

2015/10/07 07:36

コメントありがとうございます。 getActivity().finish(); をそちらに記載しても変わらず、startActivity(intent)でエラーになってしまいます。 非同期処理を開始した時点でActivityとFragmentが破棄されてしまい、 postExecute()に返ってきた時には どことも接続がされていない状態のようです。 非同期前にActivityを保持させて、 非同期処理後に保持させてあるActivityを呼び出して という処理を http://www.garunimo.com/program/p17.xhtml 等でおこなったのですが、 同じ結果となってしまいました。
GH_usami13

2015/10/07 09:00

今回は、setPositiveButtonのclick時には 画面遷移の処理はおこなわず、 非同期処理だけおこない、 元のActivity側で画面遷移の処理をおこなったら 期待した処理ができました。 この度は、長々とお付き合いいただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問