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

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

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

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

4782閲覧

android 非同期処理で得た値をメインスレッドの変数で受け取りたい

kasai2_s_2_s

総合スコア8

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

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

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2021/05/11 17:36

前提・実現したいこと

Android Studio 4.0
使用言語:Java

非同期処理で値を取得し、その値をメインスレッドの変数で受け取った後処理を行いたいと考えています。これを実現するにはどうすればよいでしょうか。

どなたかお詳しい方、ご教授頂けると幸いです。

実現したい処理の具体例

スマホの戻るボタンを押した際に、データベースから主キーを元に文字列を取り出し、取り出した文字列が予め存在する文字列と同じならばアラートダイアログを出力、そうでなければアクティビティを終了するという処理を行いたいです。非同期処理にしたい部分はデータベースから文字列を取得する際の処理です。以下にプログラムの例を示します。

Java

1@Override 2 public void onBackPressed() { 3 4 String string = "あああああ"; 5 6     //id = 取り出す文字列に対応する主キー 7 int id = 0; 8 9 /*************ここを非同期処理で行う**********************/ 10 11 //idに対応する文字列をデータベースから取得する処理 12 String stringFromRoom = mWordViewModel.getString(id); 13 14 /*******************************************************/ 15 16 17 if (stringFromRoom.equals(string)) { 18 19 AlertDialog.Builder builder = new AlertDialog.Builder(EditMyRouletteActivity.this); 20 builder.setMessage("アラートダイアログ") 21 .setPositiveButton("はい", new DialogInterface.OnClickListener() { 22 public void onClick(DialogInterface dialog, int id) { 23 } 24 }) 25 .setNegativeButton("いいえ", new DialogInterface.OnClickListener() { 26 public void onClick(DialogInterface dialog, int id) { 27 } 28 }) 29 .setOnCancelListener(new DialogInterface.OnCancelListener() { 30 @Override 31 public void onCancel(DialogInterface dialog) { 32 } 33 }) 34 .create() 35 .show(); 36 } else { 37       //アクティビティを終了する 38 Activity.this.finish(); 39 } 40 41 }

なぜ非同期処理をするのか

上記のプログラムの非同期処理にしたい部分を、非同期処理にせず実行した所、以下のエラーが出ました。

java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

このエラーについて調べた所、
https://stackoverflow.com/questions/59607324/error-cannot-access-database-on-the-main-thread-since-it-may-potentially-lock-t
にて、データベースにアクセスする処理は時間がかかり、メインスレッドを止めてしまうことになるため、別スレッドで実行する必要がある。とのことでした。そのため、データベースから文字列を取得するこの処理を非同期にする必要があるという考えに至りました。

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

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

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

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

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

hoshi-takanori

2021/05/11 17:47 編集

メインスレッドで非同期処理の結果を待ってしまったら、メインスレッドを止めてしまうことに変わりはありません。 そうではなく、データベースの問い合わせを開始したら一旦ボタンの処理は終了して、結果を取得したら改めて続きの処理を行うようにする必要があります。(結果が返ってくるまでの間はボタンを無効にするなどの処理も必要かも。)
kasai2_s_2_s

2021/05/12 04:18

ご回答ありがとうございます。 戻るボタンを押すことによる不具合の可能性の指摘もありがとうございました。
guest

回答1

0

ベストアンサー

こんな感じでしょうか。
関数名はいいのが思いつかなかったので、そちらで変更してください。

Android

1@Override 2 public void onBackPressed() { 3 4 String string = "あああああ"; 5 6     //id = 取り出す文字列に対応する主キー 7 int id = 0; 8 9 new Thread(new Runnable() { 10 @Override 11 public void run() { 12 //idに対応する文字列をデータベースから取得する処理 13 String stringFromRoom = mWordViewModel.getString(id); 14 actionFromString(stringFromRoom); 15 } 16 }).start(); 17 } 18 19 private void actionFromString(String stringFromRoom) { 20 runOnUiThread(new Runnable() { 21 public void run() { 22 showUiDialog(stringFromRoom); 23 } 24 } 25 } 26 27 private void showUiDialog(String stringFromRoom) { 28 if (stringFromRoom.equals(string)) { 29 30 AlertDialog.Builder builder = new AlertDialog.Builder(EditMyRouletteActivity.this); 31 builder.setMessage("アラートダイアログ") 32 .setPositiveButton("はい", new DialogInterface.OnClickListener() { 33 public void onClick(DialogInterface dialog, int id) { 34 } 35 }) 36 .setNegativeButton("いいえ", new DialogInterface.OnClickListener() { 37 public void onClick(DialogInterface dialog, int id) { 38 } 39 }) 40 .setOnCancelListener(new DialogInterface.OnCancelListener() { 41 @Override 42 public void onCancel(DialogInterface dialog) { 43 } 44 }) 45 .create() 46 .show(); 47 } else { 48       //アクティビティを終了する 49 this.finish(); 50 } 51 52 }

DB処理や通信処理など、時間がかかるものはバックグラウンドスレッドで処理するというのが基本にあります。
時間がかかった場合、ANRが発生してしまうからです。
https://developer.android.com/training/articles/perf-anr?hl=ja
こちらを参照してください。

また、ダイアログなどのUI表示はメインスレッドで行う必要があります。
ですので、UI変更する際にはメインスレッドに置き換える必要があります。

投稿2021/05/12 01:14

編集2021/05/12 01:23
rinjinto

総合スコア170

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

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

rinjinto

2021/05/12 02:52 編集

なお、この方法ではhoshi-takanoriさんが記載されている連打の対策はできていません。 連打対策するのであれば、DBへのアクセス処理をsynchronized宣言をする感じでしょうか。
kasai2_s_2_s

2021/05/12 04:24

ご回答ありがとうございます。 頂いたコードを動かした所、正常に動くことを確認することができました。 また、連打対策についてのご指摘ありがとうございます。頂いた情報を元に対策を進めようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問