2017-04-25 3 views
0

J'ai besoin d'utiliser runOnUiThread pour mettre à jour un TextView dans l'interface utilisateur dans un thread de travail qui reçoit des chaînes d'un service Web. J'ai regardé d'autres articles ici et j'ai essayé de mettre en œuvre les solutions proposées, mais quand je démarre mon application, elle plante. Je ne suis pas très familier avec cette méthode, j'ai donc besoin d'indications sur la façon de résoudre ce problème.Comment implémenter correctement runOnUiThread Android

04-25 12: 19: 59,917 4108-4108 /? I/art: Pas de validation en retard -Xcheck: jni (déjà activé) 04-25 12: 19: 59.917 4108-4108 /? W/art: Variante CPU inattendue pour X86 utilisant les valeurs par défaut: x86 04-25 12: 20: 00.147 4108-4108/com.example.gmars.parseltonguev2 W/Système: ClassLoader référencé chemin inconnu: /data/app/com.example I/InstantRun: démarrage du serveur d'exécution instantanée: processus principal 04-25 00.218 4108-4108/com.example.gmars.parseltonguev2 D/AndroidRuntime: Arrêt de la machine virtuelle 04-25 12: 20: 00.218 4108-4108/com.example.gmars.parseltonguev2 E/AndroidRuntime: FATAL EXCEPTION: principal Processus: com.example.gmars.parseltonguev2, PID: 4108 java.lang.RuntimeException: Impossible d'instancier l'activité ComponentInfo {com.example.gmars.parseltonguev2/com.example.gmars.parseltonguev2.MainActivity}: java.lang.NullPointer Exception: Tentative d'invocation de la méthode virtuelle 'android.view.Window $ Callback android.view.Window.getCallback()' sur une référence d'objet nul at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2548) at android. app.ActivityThread.handleLaunchActivity (ActivityThread.java:2707) at android.app.ActivityThread.-wrap12 (ActivityThread.java) à l'adresse android.app.ActivityThread $ H.handleMessage (ActivityThread.java:1460) at android.os .Handler.dispatchMessage (Handler.java:102) at android.os.Looper.loop (Looper.java:154) at android.app.ActivityThread.main (ActivityThread.java:6077) à java.lang.reflect.Method.invoke (méthode native) à com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:865) à com.android.internal.os.ZygoteInit.main (ZygoteInit.java:755) Causée par: java.lang.NullPointerException: Tentative d'invocation de la méthode virtuelle 'android.view.Window $ Callback android.view.Window.getCallback()' sur une référence d'objet nul at android.support. v7.app.AppCompatDelegateImplBase. (AppCompatDelegateImplBase.java:120) à android.support.v7.app.AppCompatDelegateImplV9. (AppCompatDelegateImplV9.java:155) à android.support.v7.app.AppCompatDelegateImplV11. (AppCompatDelegateImplV11.java:31) à android.support.v7.app.AppCompatDelegateImplV14. (AppCompatDelegateImplV14.java:55) à android.support.v7.app.AppCompatDelegateImplV23. (AppCompatDelegateImplV23.java:33) à android.support.v7.app.AppCompatDelegateImplN. (AppCompatDelegateImplN.java:33) à android.support.v7.app.AppCompatDelegate.create (AppCompatDelegate.java:201) à android.support.v7.app.AppCompatDelegate.create (AppCompatDelegate.java:185) à androïde. support.v7.app.AppCompatActivity.getDelegate (AppCompatActivity.java:519) at android.support.v7.app.AppCompatActivity.findViewById (AppCompatActivity.java:190) à com.example.gmars.parseltonguev2.MainActivit y. (MainActivity.java:30) à java.lang.Class.newInstance (méthode native) à android.app.Instrumentation.newActivity (Instrumentation.java:1078) at android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2538) à l'adresse android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2707) at android.app.ActivityThread. -wrap12 (ActivityThread.java) at android.app.ActivityThread $ H.handleMessage (ActivityThread.java:1460) à l'adresse android.os.Handler.dispatchMessage (Handler.java:102) at android.os.Looper.loop (Looper.java:154) at android.app.ActivityThread.main (ActivityThread.java:6077) à java.lang.reflect.Method.invoke (méthode native) à com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:865) à com.android.internal.os.ZygoteInit.main (ZygoteInit.java:755)

Activity updateUI; 

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

    updateUI = this; 

    itemList = new ArrayList<>(); 

    new GetItemAvailability().execute(); 

} 

@Override 
    public Void doInBackground(Void... arg0) { 
     HttpHandler handler = new HttpHandler(); 

     String JSON_DATA = handler.makeServiceCall(url); 

     Log.e(TAG, "Response from url: " + JSON_DATA); 

     if (JSON_DATA != null) { 
      JSON_DATA = JSON_DATA.substring(JSON_DATA.indexOf('{'),JSON_DATA.lastIndexOf('}')+1); 
      Log.e(TAG, "Substring of response: " + JSON_DATA); 
      try { 
       JSONObject reader = new JSONObject(JSON_DATA); 

       JSONObject availability = reader.getJSONObject("availability"); 

       final String availableQuantity = availability.getString("availableQuantity"); 
       final String defaultBranch = availability.getString("defaultBranch"); 
       final String defaultInventoryBranch = availability.getString("defaultInventoryBranch"); 
       final String inventoryBranch = availability.getString("inventoryBranch"); 
       final String footage = availability.getString("footage"); 
       final String anticipatedStockDate = availability.getString("anticipatedStockDate"); 
       final String discontinuedItemFlag = availability.getString("discontinuedItemFlag"); 
       final String mdc = availability.getString("mdc"); 
       final String mdcquantity = availability.getString("mdcquantity"); 

       HashMap<String, String> item = new HashMap<>(); 

       item.put("availableQuantity", availableQuantity); 
       item.put("defaultBranch", defaultBranch); 
       item.put("defaultInventoryBranch", defaultInventoryBranch); 
       item.put("inventoryBranch", inventoryBranch); 
       item.put("footage", footage); 
       item.put("anticipatedStockDate", anticipatedStockDate); 
       item.put("discontinuedItemFlag", discontinuedItemFlag); 
       item.put("mdc", mdc); 
       item.put("mdcquantity", mdcquantity); 

       itemList.add(item); 

       updateUI.runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
         tvAvailableQuantity.setText(availableQuantity); 
         tvDefaultBranch.setText(defaultBranch); 
         tvDefaultInventoryBranch.setText(defaultInventoryBranch); 
         tvInventoryBranch.setText(inventoryBranch); 
         tvFootage.setText(footage); 
         tvAnticipatedStockDate.setText(anticipatedStockDate); 
         tvDiscontinuedItemFlag.setText(discontinuedItemFlag); 
         tvMdc.setText(mdc); 
         tvMdcquantity.setText(mdcquantity); 
        } 
       }); 

      } 
+1

Vous devez initialiser les variables de l'interface utilisateur, par exemple 'TextView tvAvailableQuantity = (TestView) findViewById (id)' – anatoli

+0

Pourriez-vous éditer votre question et ajouter la stacktrace du crash? Cela n'a peut-être rien à voir avec 'runOnUiThread()' et cela nous donnera plus d'informations. –

+0

Je l'ai fait juste avant la méthode onCreate avec mes autres variables. J'ai seulement posté des extraits du code concernant le runOnUiThread. Merci. –

Répondre

0

Votre implémentation de runOnUiThread() est correcte. Vous lui passez un runnable qui est exécuté sur le thread UI.

Dans votre cas, cependant, je pense que ce n'est pas même nécessaire si vous changez le type de résultat de votre AsyncTask à cordes, vous pouvez simplement revenir JSON_DATA de la méthode doInBackground() et déplacer le reste du code dans onPostExecute() qui court sur la UI thread de toute façon.

+0

Merci, j'avais mes TextViews initialisés avant onCreate. Cependant, quelle est la meilleure pratique, pour utiliser runOnUiThread ou votre méthode? –

+0

Normalement, vous utilisez runOnUiThread si vous devez, par exemple, montrer quelque chose à l'utilisateur pendant que vous êtes en train de faire quelque chose dans un fil différent. Dans votre cas, votre accès au réseau (qui a demandé le thread séparé en premier lieu) est déjà terminé, donc dans ce cas, je dirais que ma suggestion serait préférable ici - il est également plus facile à lire, un peu plus court et vous n'avez pas besoin de créer l'objet Runnable. – Ridcully