2017-02-02 4 views
2

このコードをテストして、uiコンポーネントをバックグラウンドスレッドから変更するとアプリがクラッシュするかどうかを確認しました。しかしそれはしませんでした。スレッドは、アクティビティライフサイクルメソッド内から開始された場合、UIを変更することができます。どうして?

ここにコードが追加されました。私はMainActivityonCreate()方法で新しいスレッドを開始し、それはクラスでは

を言うandroid docsごとに墜落している必要があり、Runnable.run()メソッドが実行さ のコードが含まれています。通常、何かはRunnableで許されます。ただし、 を覚えておいてください。RunnableはUIスレッド上で実行されないため、 はViewオブジェクトなどのUIオブジェクトを直接変更できません。

私はそれがクラッシュすると予想していました。それはなかった。コードを参照してください -

public class MainActivity extends AppCompatActivity { 

    TextView txt; 
    Thread thread; 
    Runnable runnable = new Runnable() { 
    @Override 
    public void run() { 
     txt.setText("bro"); 
    } 
    }; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    txt = (TextView) findViewById(R.id.name_txt); 
    thread = new Thread(runnable); 
    thread.start(); 
    } 
} 

それがクラッシュをし、以下のようonClicklistener()からスレッドを開始しながら、私はUIを変更しようとしながら。これは期待される。

public class MainActivity extends AppCompatActivity { 

    TextView txt; 
    Thread thread; 
    Runnable runnable = new Runnable() { 
    @Override 
    public void run() { 
    txt.setText("bro"); 
    } 
    }; 

    View.OnClickListener listener = new View.OnClickListener() { 
    @Override 
    public void onClick(View v) { 
    thread.start(); 
    } 
    }; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    txt = (TextView) findViewById(R.id.name_txt); 
    thread = new Thread(runnable); 
    txt.setOnClickListener(listener); 
    } 
} 

ここで、期待されている第2のコードスニペットがクラッシュ、及び最初のものがないこと。

私は毎回新しいワーカースレッドを作成していますが、別の場所で作成しているので、なぜこのようなことが起こっているのか説明してください。公式のドキュメントの参考になるでしょう。

+0

最初のスニペットで 'btn'とは何ですか、あなたは1つのスニペットにリンクしていて、別のものにテキストを割り当てています – OBX

+1

このクラッシュはビューのレンダリングに先立って起こりません。最初のケースでは、ビューのプロパティ(テキスト)がビューオブジェクトに設定されていて、ビューがメインスレッドでレンダリングするのを待機しています。しかし、2番目のケースでは、ビューがレンダリングされ、setTextへの呼び出しがすぐにバックグラウンドスレッドで実行され、クラッシュする可能性があります。 – Krish

+0

@OBXはそれを修正しました。 –

答えて

2

私の質問のコメントで@krishが指摘したように、この動作の背後にある理由がわかりました。その理由は、スレッドは、UIスクリーン上に表示されない、すなわちレンダリングされなくなるまで、TextViewオブジェクト内でのみ変更を行うことができたからです。メインスレッドを除くすべてのスレッドがUIコンポーネントに変更を加えないことがあるのは、ビューレンダリングの後だけです。ビューオブザーバを使って、ビューが変更前にレンダリングされたかどうかを確認しようとしました。ビューレンダリングの前に変更が加えられたことが示されました。

ここに私が試したコードです。

public class MainActivity extends AppCompatActivity { 

    TextView txt; 
    Thread thread; 
    Runnable runnable = new Runnable() { 
    @Override 
    public void run() { 
     txt.setText("bro"); 
     Log.d("ThreadTest", "The Text was changed."); 
    } 
    }; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    txt = (TextView) findViewById(R.id.name_txt); 
    thread = new Thread(runnable); 

    txt.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 
     @Override 
     public void onGlobalLayout() { 
     Log.d("ThreadTest", "The TextView was rendered"); 
     } 
    }); 
    } 

    @Override 
    protected void onResume() { 
    super.onResume(); 
    thread.start(); 
    } 
} 

上記のコードを使用します。出力に表示されます:

テキストが変更されました。

のTextViewはテキストがビューのレンダリング前に変更されたことを意味し、どの

をレンダリングしました。あなたがonGlobalLayoutメソッドで変更を加えるためにスレッドを開始しようとすると。それが必要なアプリケーションがクラッシュします。

0

UIはthread-safeではありません。processes-and-threadsを参照してください。あなたは、あなたを待っている多くの地雷の1つにヒットしなかっただけで幸運でした。
あなたは運に頼る好きではない場合:
をあなたが使用してする必要があります。

runOnUiThread(runnable); 

の代わり:

thread = new Thread(runnable); 

AsyncTaskは、UIスレッドの適切かつ容易に使用できるようになります。

+0

あなたの答えはジョンですが、私はすでに解決策を見つけました。 私はちょうど私が何も見つけることができなかったので、ここに正当な理由を探しています。 私があなたを間違っていると私を修正してください。あなたの答えからわかるものは、UIはスレッドセーフではないということは、別のスレッドからUIを変更するかもしれないが、クラッシュするかどうかはわかりません。私が使用した最初のコードスニペットは、mayの場合または条件をクラッシュさせない場合があります。 –

+0

@AkashRaghavはい、あなたはそれがクラッシュすることは確かではありませんが、そのポイントは何ですか?ドキュメンテーションはあなたに何かをしないように指示しますが、とにかくそれをやりたいのですか?どうして ? –

+1

私はそれをしたくありません。私はちょっと後ろに起こっていることを知りたい。この動作のロジックまたは理由。 coz、何かが文書化されているなら、指定されたもののように動作しなければならない。そうでなければ、文書化のポイントは何か。 –

関連する問題