2016-09-16 9 views
-1

TextViewという1つのアクティビティで構成されるアプリを作成しました。"ビュー階層を作成した元のスレッドのみがそのビューに触れることができます。エラーが発生しました。

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:paddingBottom="0dp" 
    android:paddingLeft="0dp" 
    android:paddingRight="0dp" 
    android:paddingTop="0dp" 
    tools:context="zeratops.myApp.MainActivity"> 

    <FrameLayout 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentStart="true" 
     android:background="#000000" 
     android:layout_alignParentTop="true"> 

     <TextView 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:textSize="14dp" 
      android:text="" 
      android:textColor="#FF0000" 
      android:id="@+id/text_1" 
      android:paddingTop="200dp" 
      android:layout_gravity="center" /> 
    </FrameLayout> 
</RelativeLayout> 

私のJavaコードは、このtextView秒ごとのテキストを設定することです

activity_main.xml:ここに私の活動のXMLです。ここで私は、このタスクを実行するために使用するコードは次のとおりです。

MainActivity.java

public class MainActivity extends AppCompatActivity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     final TextView text = (TextView) findViewById(R.id.text_1); 
     Timer timer = new Timer(); 
     TimerTask timertask = new TimerTask() { 
      @Override 
      public void run() { 
       text.setText("test"); 
      } 
     }; 

     timer.schedule(timertask, 0, 1000); 
    } 
} 

問題

私は私のアプリをロードし、それを起動起動したときに、私は、次の問題に直面しています私のLG G2の:

android.view.ViewRootImpl $ CalledFromWrongThreadException:のみ元のthreビュー階層を作成した広告はそのビューに触れることができます。私はそれを削除するとき、私は例外を持っていないので、エラーの原因となって

timer.schedule(timertask, 0, 1000); 

私はラインを同定しました。私はいくつかのチェックをしていますか?

+0

JDKでは、 'Text.setText(" test ");を' Platform.runLater(){} 'で囲みます。アンドロイドには同様のものが必要です。 – shinzou

答えて

0

あなたrun()方法は、バックグラウンドスレッドで呼び出されます、そして、それは結果として、UIを操作することはできません。

軽量ソリューションは、次のようになります。

public class MainActivity extends AppCompatActivity { 
    private TextView text; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     text = (TextView) findViewById(R.id.text_1); 

     onEverySecond.run(); 
    } 

    private Runnable onEverySecond=new Runnable() { 
     @Override 
     public void run() { 
      text.setText("test"); 
      text.postDelayed(this, 1000); 
     } 
    } 
} 

postDelayed()指定された遅延期間の後、メインアプリケーションスレッドであなたのrun()メソッドを呼び出します。ここでは、それを使用してRunnableスケジュールを1000ms後に再実行するようにします。

postDelayed()「ループ」を停止するには、MainActivityremoveCallbacks(onEverySecond)と電話をかけてください。

TimerTaskrunOnUiThread()を使用しての上に、このことの利点は、あなたが別のスレッド(Timer/TimerTaskスレッド)を作成していないとして、それは、安価であるということです。

+0

パーフェクト。言及すると、スコープのエラーを避けるために、 'final TextView text =(TextView)findViewById(R.id.text_1);'インスタンスを 'public void run(){'関数の中に置かなければなりませんでした。しかし、それがなければ、それは日をかなりうまく節約する! –

+0

@Zeratops:または、フィールドにする - 私は答えを表示して更新しました。 'findViewById()'コールを不必要に毎秒行うことを防ぎます。 – CommonsWare

+0

正常に動作することを確認しました。更新していただきありがとうございます。 –

0

あなたは、UIスレッドで

text.setText("test");

を実行する必要があります。ハンドラを使用するとそうすることができます。

final Handler myHandler = new Handler(); 
myHandler.post(myRunnable); 



    final Runnable myRunnable = new Runnable() { 
     public void run() { 
     text.setText("test"); 
     } 
    }; 
関連する問題