やりたいこと
「別スレッドの処理が終わるまで、メインスレッドの処理を待機する」的な処理を実装します。
ちなみに
昔はAsyncTaskクラスがよく使われたらしいけど、APIレベル30で非推奨になったっぽい。公式ドキュメントは「java.util.concurrentを使ってね」って言ってるので素直にそっちを使いましょう。
使用例
AndroidでサーバーからJSONを取得する際など。AndroidではHTTPS通信をメインスレッドでは行なえないので、新しいスレッドを立てる必要があります。
- Stringを定義する
- https通信してInputStreamを取得
- 別メソッドで文字列に整形
- 整形した文字列を定義したStringに格納
- Stringを返す。
みたいな処理を実装してみましょう。
parseInputStreamToString
は別のところで自作したメソッドです。InputStreamを渡すと文字列に整形してくれます。
public String getJsonFromServer(String urlString){
CountDownLatch latch = new CountDownLatch(1)
String[] jsonString= new String[1];
//ここで新しいスレッドを立ち上げる
new Thread(new Runnable() {
@Override
public void run() {
HttpsURLConnection connection = null;
try {
URL url = new URL(urlString);
connection = (HttpsURLConnection) url.openConnection();
jsonString[0] = parseInputStreamToString(connection.getInputStream());
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
connection.disconnect();
latch.countDown();
}
}
}).start();
latch.await();
return jsonString[0];
}
「別スレッドの処理が終わるまで、メインスレッドの処理を待機する」のような処理をしないと、通信が終わっていないのにreturn文までたどり着き、nullを返してしまうことがあります。
解説
CountDownLatchのawait()
メソッドは、引数で与えられた数が0になるまでスレッドの処理を中断してくれます。countDown()
が呼び出されるたびに与えられた数が1ずつ減っていくので、for文と組み合わせると「配列内の要素すべての処理が終わるまで待つ」みたいな処理も実装することができます。
参考