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

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

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

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

Android

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

Android Studio

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

Q&A

解決済

1回答

7382閲覧

AndroidにおけるHandlerやRunnableの書く場所について

Mariydi

総合スコア9

Java

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

Android

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

Android Studio

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

0グッド

0クリップ

投稿2019/02/28 15:03

編集2019/03/04 14:03

前提・今やっていること

超初心者です。初めて質問します。
Android StudioでHTTP通信をする電卓を作っています。
その2つを組み合わせる意味は特に無いです。基礎をまとめてやっちゃおうという感じです。

クライアントはJavaで書いています。
クライアントの通信にはokhttp3を採用して、非同期で通信しています。
メインスレッドからokhttp3のスレッドに値を渡してサーバと通信、レスポンスを受け取ることまではできました。
そこから、メインスレッドへ値を渡してテキストボックスに表示させたいのですが、HandlerとThread、Runnableの書くべき場所がわかりません。

私が今うっすらと思ってることは
・メインスレッドのメインクラス?の中でHandlerを宣言する必要がある
・サブスレッドでvoid run()をどこでもいいから書かないといけない?
・サブスレッドでHandlerは書かなくて良い
・そのrun()に到達すると、メインスレッドのHandlerに渡ってrun()の中に書いてあったことが実行される…?
・結局スレッドってどこで使うの?

試行錯誤してるソースコードが以下です…

なんか支離滅裂な文章ですが…足りない情報があれば随時補足します!

メインスレッドのソースコード

Java

1package com.example.hogehoge.calculater; 2 3import android.os.Handler; 4import android.os.HandlerThread; 5import android.os.Looper; 6import android.os.Message; 7 8import android.support.v7.app.AppCompatActivity; 9import android.os.Bundle; 10import android.view.View; 11import android.widget.Button; 12import android.widget.TextView; 13 14public class MainActivity extends AppCompatActivity { 15 16 TextView textView; 17 Button button; 18 Handler handler = new Handler(); 19 20 @Override 21 protected void onCreate(Bundle savedInstanceState) { 22 super.onCreate(savedInstanceState); 23 setContentView(R.layout.activity_main); 24 25 26 textView = (TextView) findViewById(R.id.formula); 27 28 findViewById(R.id.num1).setOnClickListener(buttonNumberListener); 29 findViewById(R.id.num2).setOnClickListener(buttonNumberListener); 30 findViewById(R.id.num3).setOnClickListener(buttonNumberListener); 31 findViewById(R.id.num4).setOnClickListener(buttonNumberListener); 32 findViewById(R.id.num5).setOnClickListener(buttonNumberListener); 33 findViewById(R.id.num6).setOnClickListener(buttonNumberListener); 34 findViewById(R.id.num7).setOnClickListener(buttonNumberListener); 35 findViewById(R.id.num8).setOnClickListener(buttonNumberListener); 36 findViewById(R.id.num9).setOnClickListener(buttonNumberListener); 37 findViewById(R.id.num0).setOnClickListener(buttonNumberListener); 38 findViewById(R.id.coron).setOnClickListener(buttonNumberListener); 39 findViewById(R.id.NEXT_INT).setOnClickListener(buttonNumberListener); 40 findViewById(R.id.add).setOnClickListener(buttonNumberListener); 41 findViewById(R.id.substract).setOnClickListener(buttonNumberListener); 42 findViewById(R.id.divide).setOnClickListener(buttonNumberListener); 43 findViewById(R.id.multiply).setOnClickListener(buttonNumberListener); 44 findViewById(R.id.Clear).setOnClickListener(buttonNumberListener); 45 findViewById(R.id.equal).setOnClickListener(buttonNumberListener); 46 findViewById(R.id.BACK).setOnClickListener(buttonNumberListener); 47 } 48 49 View.OnClickListener buttonNumberListener = new View.OnClickListener() { 50 @Override 51 public void onClick(View view) { 52 Button button = (Button) view; 53 54 55 switch (view.getId()){ 56 case R.id.NEXT_INT: 57 textView.append(" "); 58 break; 59 case R.id.Clear: 60 textView.setText(""); 61 break; 62 case R.id.BACK: 63 if (textView.length() > 0 && textView.getText() != null) { 64 String temp = textView.getText().toString(); 65 temp = temp.substring(0, temp.length() - 1); 66 textView.setText(temp); 67 } 68 break; 69 case R.id.equal: 70 HttpClient.okhttp3Client(textView.getText().toString()); 71 break; 72 default: 73 textView.append(button.getText()); 74 } 75 } 76 }; 77 78 //以下のメソッドを新しく追加しました。 79 public void CompAnswer(Looper toLooper,final String Answer) { 80 setContentView(R.layout.activity_main); 81 textView = (TextView) findViewById(R.id.formula); 82 new Handler(toLooper).post(new Runnable() { 83 @Override 84 public void run() { 85 86 //このテキストビューまでは到達できました。 87 //実行しようとするとアプリ自体が落ちることは確認できました。 88 textView.setText(Answer); 89 90 return; 91 } 92 }); 93 } 94}

HttpClientのソースコード

Java

1package com.example.hogehoge.calculater; 2 3import android.os.Looper; 4 5import java.io.IOException; 6 7import okhttp3.Callback; 8import okhttp3.MediaType; 9import okhttp3.OkHttpClient; 10import okhttp3.Call; 11import okhttp3.Request; 12import okhttp3.RequestBody; 13import okhttp3.Response; 14 15 16public class HttpClient { 17 18 MainActivity test1; 19 20 static void okhttp3Client(final String strNum) { 21 // TODO Auto-generated method stub 22 23 String url = "http://hogehoge.site"; 24 OkHttpClient client = new OkHttpClient(); 25 26 27 try { 28 29 Request request = new Request.Builder() 30 .url(url) 31 .post(RequestBody.create(MediaType.parse("text/plain;charset=utf-8"),strNum)) 32 .build(); 33 34 Call call = client.newCall(request); 35 call.enqueue(new Callback() { 36 @Override 37 public void onFailure(Call call, IOException e) 38 { 39 //エラー処理を書く 40 } 41 42 @Override 43 public void onResponse(Call call, Response response) throws IOException 44 { 45 //この1行を追加しました。 46 new MainActivity().CompAnswer(Looper.getMainLooper(),response.body().string()); 47 } 48 }); 49 50 51 }catch(Exception e) { 52 53 } 54 } 55} 56

エラー文

ErorrMessage

1 java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.Window$Callback android.view.Window.getCallback()' on a null object reference 2 at android.support.v7.app.AppCompatDelegateImpl.<init>(AppCompatDelegateImpl.java:249) 3 at android.support.v7.app.AppCompatDelegate.create(AppCompatDelegate.java:182) 4 at android.support.v7.app.AppCompatActivity.getDelegate(AppCompatActivity.java:520) 5 at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:140) 6 at com.example.hogehoge.calculater.MainActivity.CompAnswer(MainActivity.java:79) 7 at com.example.hogehoge.calculater.HttpClient.okhttp3Client(HttpClient.java:24) 8 at com.example.hogehoge.calculater.MainActivity$1.onClick(MainActivity.java:70) 9 at android.view.View.performClick(View.java:6294) 10 at android.view.View$PerformClick.run(View.java:24770) 11 at android.os.Handler.handleCallback(Handler.java:790) 12 at android.os.Handler.dispatchMessage(Handler.java:99) 13 at android.os.Looper.loop(Looper.java:164) 14 at android.app.ActivityThread.main(ActivityThread.java:6494) 15 at java.lang.reflect.Method.invoke(Native Method) 16 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 17 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 18

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

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

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

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

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

guest

回答1

0

ベストアンサー

メインスレッドのメインクラス?の中でHandlerを宣言する必要がある

メインスレッド内で, 使用する前であればどこでも良いですが, 通常は極力使用する直前に行うと思います.
また, メインスレッド内で無くても, Handler のコンストラクタのパラメータとして Looper.getMainLooper() を渡せば, 大丈夫と思います.

サブスレッドでvoid run()をどこでもいいから書かないといけない?

この run() とは Handler で実行したい処理のことでしょうか. でしたら, Runnable を実装したクラスの中に書かなければなりません. そのクラスのインスタンスを Handler の post メソッドに渡す形になります.
サブスレッドで…というのは意味が分かりません.

サブスレッドでHandlerは書かなくて良い

上で言われている宣言のことでしょうか. 2つは要らないと思います.

そのrun()に到達すると、メインスレッドの Handler に渡ってrun()の中に書いてあったことが実行される…?

逆と思います. Handler の post メソッドに Runnable を実装し( run() に必要な処理を書い) たクラスのインスタンスを渡しますと, UIスレッドにて run() が実行されます.

結局スレッドってどこで使うの?

どのスレッドのことでしょうか.
メインスレッドは常に使われております.
OkHttp は, おそらく call.enqueue によってスレッドが使用されていると思います.


かなり豪快なコードになっていると思います.

//この1行を追加しました。
new MainActivity().CompAnswer(Looper.getMainLooper(),response.body().string());

Activity は Android システムが管理していますので, 勝手に生成しても Activity としては機能いたしません. ですので findViewById が null を返しているのではないでしょうか.
必要であれば okhttp3Client のパラメータとして受け取って使用してください.

また逆に CompAnswer は Looper をパラメータとして受け取って Handler を生成していますが, CompAnswer は MainActivity のメソッドですので, MainActivity で先に生成済みの Handler handler = new Handler(); の handler が使用できると思います.

コード量と動作を考えますと, HttpClient クラスがあることによって動作イメージが崩れているのではないでしょうか. クラス分けは大事ですが, この場合 Http の処理は OkHttp が行っていますので, いっそ HttpClient クラスは無いほうが良いと思います.
(ついでですが, 各ボタンのリスナを全て同じにした上でリスナ内でボタンにより分岐するのでは無く, 専用処理があるボタンには専用リスナを設定したほうが分かり易いと思います.)

java

1package com.example.hogehoge.calculater; 2 3import android.os.Bundle; 4import android.os.Handler; 5import android.support.v7.app.AppCompatActivity; 6import android.view.View; 7import android.widget.Button; 8import android.widget.TextView; 9 10import java.io.IOException; 11 12import okhttp3.*; 13 14public class MainActivity extends AppCompatActivity { 15 16 TextView formulaTextView; 17 Handler handler = new Handler(); 18 19 @Override 20 protected void onCreate(Bundle savedInstanceState) { 21 super.onCreate(savedInstanceState); 22 setContentView(R.layout.activity_main); 23 24 formulaTextView = (TextView) findViewById(R.id.formula); 25 26 View.OnClickListener NumListener = new View.OnClickListener() { 27 @Override 28 public void onClick(View view) { 29 formulaTextView.append(((Button)view).getText()); 30 } 31 }; 32 33 findViewById(R.id.num1).setOnClickListener(NumListener); 34 findViewById(R.id.num2).setOnClickListener(NumListener); 35 findViewById(R.id.num3).setOnClickListener(NumListener); 36 findViewById(R.id.num4).setOnClickListener(NumListener); 37 findViewById(R.id.num5).setOnClickListener(NumListener); 38 findViewById(R.id.num6).setOnClickListener(NumListener); 39 findViewById(R.id.num7).setOnClickListener(NumListener); 40 findViewById(R.id.num8).setOnClickListener(NumListener); 41 findViewById(R.id.num9).setOnClickListener(NumListener); 42 findViewById(R.id.num0).setOnClickListener(NumListener); 43 44 findViewById(R.id.coron).setOnClickListener(NumListener); 45 46 findViewById(R.id.add).setOnClickListener(NumListener); 47 findViewById(R.id.substract).setOnClickListener(NumListener); 48 findViewById(R.id.divide).setOnClickListener(NumListener); 49 findViewById(R.id.multiply).setOnClickListener(NumListener); 50 51 findViewById(R.id.NEXT_INT).setOnClickListener(new View.OnClickListener() { 52 @Override 53 public void onClick(View view) { 54 formulaTextView.append(" "); 55 } 56 }); 57 findViewById(R.id.Clear).setOnClickListener(new View.OnClickListener() { 58 @Override 59 public void onClick(View view) { 60 formulaTextView.setText(""); 61 } 62 }); 63 findViewById(R.id.equal).setOnClickListener(new View.OnClickListener() { 64 @Override 65 public void onClick(View view) { 66 okhttp3Client(formulaTextView.getText().toString()); 67 } 68 }); 69 findViewById(R.id.BACK).setOnClickListener(new View.OnClickListener() { 70 @Override 71 public void onClick(View view) { 72 Button button = (Button) view; 73 if (formulaTextView.length() > 0 && formulaTextView.getText() != null) { 74 String temp = formulaTextView.getText().toString(); 75 temp = temp.substring(0, temp.length() - 1); 76 formulaTextView.setText(temp); 77 } 78 } 79 }); 80 } 81 82 void okhttp3Client(final String formula) { 83 String url = "http://hogehoge.site"; 84 OkHttpClient client = new OkHttpClient(); 85 86 try { 87 Request request = new Request.Builder() 88 .url(url) 89 .post(RequestBody.create(MediaType.parse("text/plain;charset=utf-8"), formula)) 90 .build(); 91 Call call = client.newCall(request); 92 call.enqueue(new Callback() { 93 @Override 94 public void onFailure(Call call, IOException e) { 95 //エラー処理を書く 96 } 97 @Override 98 public void onResponse(Call call, Response response) throws IOException { 99 //この1行を追加しました。 100 compAnswer(response.body().string()); 101 } 102 }); 103 } catch(Exception e) { 104 105 } 106 } 107 108 //以下のメソッドを新しく追加しました。 109 private void compAnswer(final String Answer) { 110 handler.post(new Runnable() { 111 @Override 112 public void run() { 113 114 //このテキストビューまでは到達できました。 115 //実行しようとするとアプリ自体が落ちることは確認できました。 116 formulaTextView.setText(Answer); 117 } 118 }); 119 } 120}

投稿2019/02/28 17:08

編集2019/03/04 16:29
jimbe

総合スコア12646

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

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

Mariydi

2019/03/03 15:09

コンストラクタとかいろいろ調べたら簡単なのは動いてくれるようになりました! ありがとうございます! …でも、ハンドラー内部でTextViewの値を変更しようと思ったらできなくて… メインクラスの中にメインメソッドとHandlerを記載した別のメソッドがあるんですけど、それぞれで一つのTextViewを変更する方法とかありますか…? うーん…日本語おかしかったらすいません
jimbe

2019/03/03 15:41 編集

ご質問に提示済みのコードを(説明の追記とともに)最新に更新して頂いたほうが, 言葉で説明頂くよりも早いかと思います. 『百聞は一見に如かず』ですね. 日本語はおかしくないと思いますが, お言葉が足りません. 「できなくて」とはどういった状況でしょうか. そのように動作すると期待されるコードを書かれても, 何のエラーも無く表示もされないのでしょうか. なにやらエラーが表示されるけれども意味が分からないということでしょうか. それとも, そのように動作するようなコードが思い付かれないということでしょうか.
Mariydi

2019/03/04 14:09

更新しました! なるほど、できないと判断するに至った過程と状況、エラー文などの周辺情報が足りなかったのですね… 申し訳ないです。気をつけます。 Handlerを使ってhttpのレスポンスをtextViewに反映すると期待するコードを書きましたが、NullPointerExceptionが表示されました。 メインメソッドとは別メソッドなので宣言もしたのですが更新できません。 この状況を打破するコードを思いつかないのでご教示願えませんでしょうか。
jimbe

2019/03/04 16:31

回答に追記致しました.
Mariydi

2019/03/05 10:32

回答の追記ありがとうございます! すごくわかりやすいです。 確かにどういう動きをするんだっけ?とよく読み返してました。 クラス分けはしないほうが動きそうですね… ファイル分けてクラス分けたらそれも勉強になるかなとか思っただけなので、jimbeさんに提案していただいたコードを参考にさせていきたいと思います。 また、関連するコード以外の部分についてもアドバイスしていただきありがとうございます。 見やすいコードを書くことも少しずつ勉強していきたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問