2015-05-26 12 views
6

Ich habe versucht, eine App zu erstellen, die einige Thread-Nutzung haben. Während der Arbeit habe ich unvorhersehbares Verhalten festgestellt, während ich versuchte, von einem Thread auf ein TextView zuzugreifen. Ich weiß, Androide verbieten uns den Zugriff auf Ansichten direkt aus einem anderen thread.Ich weiß auch, wie auf Haupt-Thread-Ansichten von einem anderen Thread mit AsyncTask, Handler, Activity.runOnUiThread (Runnable), View.post (Runnable), View.postDelayed (Runnable , lang) usw.Unvorhersehbares Verhalten beim Zugriff auf die Ansicht von einem anderen Thread

Hier ist mein Code-Schnipsel -

public class MainActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     final TextView tv = (TextView) findViewById(R.id.tv); 
     Thread t = new Thread(new Runnable() { 

      @Override 
      public void run() { 
       /*try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       }*/ 

       /*for(int i= 0 ; i<10000000 ;i++){ 
        Log.i("logger"," i ="+i); 
        tv.setText("i = "+i); 
       }*/ 

       tv.setText("This is the new text"); 
      } 
     }); 
     t.start(); 
    } 

Wenn ich diesen Code laufen lasse, kein Absturz auftreten, aber sobald ich Thread.sleep() oder für Schleifenteil Kommentar-, crash auftreten. Kann jemand dieses Verhalten erklären, warum es so geschieht und warum Absturz nicht mit gegebenem code auftritt. Stellen Sie bitte keine Antworten dar, die erklären, wie man es macht.

Vielen Dank im Voraus.

Dies ist das Crash-Protokoll, wenn ich Kommentar- Thread.sleep() Code-Abschnitt -

05-26 21:11:47.244: E/AndroidRuntime(14310): FATAL EXCEPTION: Thread-13346 
05-26 21:11:47.244: E/AndroidRuntime(14310): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 
05-26 21:11:47.244: E/AndroidRuntime(14310): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:5225) 
05-26 21:11:47.244: E/AndroidRuntime(14310): at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1062) 
05-26 21:11:47.244: E/AndroidRuntime(14310): at android.view.View.requestLayout(View.java:15316) 
05-26 21:11:47.244: E/AndroidRuntime(14310): at android.view.View.requestLayout(View.java:15316) 
05-26 21:11:47.244: E/AndroidRuntime(14310): at android.view.View.requestLayout(View.java:15316) 
05-26 21:11:47.244: E/AndroidRuntime(14310): at android.view.View.requestLayout(View.java:15316) 
05-26 21:11:47.244: E/AndroidRuntime(14310): at android.view.View.requestLayout(View.java:15316) 
05-26 21:11:47.244: E/AndroidRuntime(14310): at android.view.View.requestLayout(View.java:15316) 
05-26 21:11:47.244: E/AndroidRuntime(14310): at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:292) 
05-26 21:11:47.244: E/AndroidRuntime(14310): at android.view.View.requestLayout(View.java:15316) 
05-26 21:11:47.244: E/AndroidRuntime(14310): at android.widget.TextView.checkForRelayout(TextView.java:6659) 
05-26 21:11:47.244: E/AndroidRuntime(14310): at android.widget.TextView.setText(TextView.java:3670) 
05-26 21:11:47.244: E/AndroidRuntime(14310): at android.widget.TextView.setText(TextView.java:3528) 
05-26 21:11:47.244: E/AndroidRuntime(14310): at android.widget.TextView.setText(TextView.java:3503) 
05-26 21:11:47.244: E/AndroidRuntime(14310): at com.example.sampleproject.MainActivity$1.run(MainActivity.java:33) 
05-26 21:11:47.244: E/AndroidRuntime(14310): at java.lang.Thread.run(Thread.java:864) 
05-26 21:11:47.284: D/memalloc(14310): ion: Mapped buffer base:0x5432a000 size:2088960 offset:0 fd:66 
+2

logcat Fehler anzeigen. –

Antwort

4

Wegen einer Race-Bedingung.

Im Wesentlichen kommt der Absturz, wenn die Ansicht versucht, sich in einem falschen Thread ungültig zu machen. setText() macht die Ansicht nicht ungültig, wenn die Ansicht nicht mindestens einmal gemessen wurde und die TextView eine mLayout ungleich Null hat.

Wenn Sie eine neue Ansichtshierarchie mit setContentView() erstellen, wird die Nachricht zur Messung der Ansichten in der Warteschlange des UI-Threads gepostet, aber die Wahrscheinlichkeit ist groß, dass der Thread ausgeführt wird, bevor der Measure Pass ein Layout für die Textansicht erstellt hat.

Für Details, überprüfen Sie die source.

0

Sie können nicht UI von einem anderen Thread aktualisieren, diese stattdessen

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    final TextView tv = (TextView) findViewById(R.id.tv); 
    Thread t = new Thread(new Runnable() { 

     @Override 
     public void run() { 

      runOnUiThread(new Runnable() { 

        @Override 
        public void run() { 
         tv.setText("This is the new text"); 
        } 
       }); 
     } 
    }); 
    t.start(); 
} 

verwenden Wenn Sie wissen möchten, mehr hier ein guter Artikel:

http://android-developers.blogspot.co.uk/2009/05/painless-threading.html

+1

Androidster hat bereits erwähnt: "Ich weiß auch, wie man von einem anderen Thread mit Hilfe von AsyncTask, Handler, Activity.runOnUiThread (Runnable), View.post (Runnable), View.postDelayed (Runnable, long) usw. auf die Ansichten des Haupt-Threads zugreift. Aber er möchte wissen, warum der Code ohne Schlaf funktioniert und nicht damit. – userv

0

Try exe Cuting jeden Code, der wie diese

runOnUiThread(new Runnable() { 
    @Override 
    public void run() { 
     // Put your UI interactions here 
    } 
}); 
0

unter Code funktioniert gut für mich mit der Benutzeroberfläche interagiert:

public class MainActivity extends Activity { 

     Handler handler = new Handler() { 
      @Override 
      public void handleMessage(Message msg) { 
       super.handleMessage(msg); 
       Bundle data = msg.getData(); 
       String result=data.getString("key"); 
       textview.setText(result); 
      } 
     }; 

     @Override 
     protected void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 

      final TextView tv = (TextView) findViewById(R.id.tv); 
      Thread t = new Thread(new Runnable() { 

       @Override 
       public void run() { 

        Bundle bundle=new Bundle(); 
        bundle.putString("key","you data"); 
        Message message=new Message(); 
        message.setData(bundle); 
        handler.sendMessage(message); 

       } 
      }); 
      t.start(); 

     } 
    } 
Verwandte Themen