web-dev-qa-db-fra.com

Android "Seul le fil d'origine qui a créé une hiérarchie de vues peut toucher ses vues." Erreur dans Fragment

J'ai cette minuterie simple dans mon application qui s'exécute toutes les 3 secondes. Cela fonctionne parfaitement s'il n'est pas dans une classe de fragments. Mais ici, en fragment, j'ai toujours eu l'erreur: seul le thread d'origine qui a créé une hiérarchie de vues peut toucher ses vues.

timer = new Timer();

timer.schedule(new TimerTask() {

    @Override
    public void run() {
        String timeStamp = new SimpleDateFormat(
                "yyyy.MM.dd HH:mm:ss").format(Calendar
                .getInstance().getTime());
        System.out.println("TimeStamp: " + timeStamp);
        // Read And Write Register Sample
        port = Integer.parseInt(gConstants.port);
        String refe = "0";// HEX Address
        ref = Integer.parseInt(refe, 16);// Hex to int
        count = 10; // the number Address to read
        SlaveAddr = 1;
        astr = gConstants.ip; // Modbus Device

        InetAddress addr;
        try {
            addr = InetAddress.getByName(astr);
            con = new TCPMasterConnection(addr); // the
            // connection
        } catch (UnknownHostException e2) {
            e2.printStackTrace();
        }

        // 1.Prepare the request
        /************************************/
        Rreq = new ReadMultipleRegistersRequest(ref, count);
        Rres = new ReadMultipleRegistersResponse();

        Rreq.setUnitID(SlaveAddr); // set Slave Address
        Rres.setUnitID(SlaveAddr); // set Slave Address

        // 2. Open the connection
        con.setPort(port);
        try {
            con.connect();
            System.out.println("Kapcsolódva!");
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        con.setTimeout(2500);
        // 3. Start Transaction
        trans = new ModbusTCPTransaction(con);
        trans.setRetries(5);
        trans.setReconnecting(true);
        trans.setRequest(Rreq);

        try {
            trans.execute();
        } catch (ModbusIOException e) {
            e.printStackTrace();
        } catch (ModbusSlaveException e) {
            e.printStackTrace();
        } catch (ModbusException e) {
            e.printStackTrace();
        }
        /* Print Response */
        Rres = (ReadMultipleRegistersResponse) trans
                .getResponse();

        System.out.println("Connected to=  " + astr
                + con.isConnected() + " / Start Register "
                + Integer.toHexString(ref));

        count = 10;
        for (int k = 0; k < count; k++) {
            System.out.println("The value READ: "
                    + Rres.getRegisterValue(k) + " "
                    + Rres.getUnitID());
            ki_adat = ki_adat + Rres.getRegisterValue(k) + "\n";


            // Adatbázisba írás
            ContentValues modbusData = new ContentValues();
            modbusData.put("Value", Rres.getRegisterValue(k)); // tábla
                                                                // +
                                                                // érték
            modbusData.put("timeStamp", timeStamp);
            try {
                gConstants.db.beginTransaction();
                gConstants.db
                        .insert("Modbus", null, modbusData);
                gConstants.db.setTransactionSuccessful();
            } finally {
                gConstants.db.endTransaction();
            }

        }
        kiir.setText(ki_adat);
        ki_adat = "";
    }//run vége

}, 0, 3000);
29
David

Cette erreur se produit lors de la tentative d'accès aux éléments d'interface utilisateur à partir d'un thread qui n'est pas le thread d'interface utilisateur.

Pour accéder/modifier des éléments à partir d'un thread non UI, utilisez runOnUIThread.

Cependant, comme vous devez changer un élément d'interface utilisateur à partir d'un fragment, runOnUIThread doit être invoqué sur l'activité propriétaire des fragments. Vous pouvez le faire via getActivity().runOnUIThread().

PAR EXEMPLE:

timer.schedule(new TimerTask() {
    @Override
    public void run() {
        // Your logic here...

        // When you need to modify a UI element, do so on the UI thread. 
        // 'getActivity()' is required as this is being ran from a Fragment.
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // This code will always run on the UI thread, therefore is safe to modify UI elements.
                myTextBox.setText("my text");
            }
        });
    }
}, 0, 3000); // End of your timer code.

Pour plus d'informations, consultez la documentation suivante:

  1. Fragments Android (spécifiquement, getActivity() ).
  2. TimerTask .
  3. Appel d'un Runnable sur le thread d'interface utilisateur.
93
matthewrdev

vous devez utiliser la fonction runOnUIThread() J'ai un exemple quelque part que je posterai quand je le trouverai.

vous devez donner à votre minuterie une instance de MainActivity voir également cette question que j'ai posée problèmes de synchronisation d'image Android avec ce qui ressemble à une chose similaire à ce que vous essayez de faire

public static void updateText(Activity act, resID)
{

 loadingText = (TextView) activity.findViewById(R.id.loadingScreenTextView);
          act.runOnUiThread(new Runnable() 
                {
                     public void run() 
                     {
                       loadingText.setText(resID);

                     }

                });
}
8
Cob50nm

Vous effectuez une opération d'interface utilisateur à partir d'un autre thread. Je vous suggère d'utiliser ce qui suit.

runOnUiThread(new Runnable() {  
                @Override
                public void run() {

                    kiir.setText(ki_adat);
                }                   
3
Ritesh Gune

2 solutions:

Et placez l'appel myTextView.setText(str) dans la méthode run () de l'objet Runnable.

2
flawyte

ESSAYEZ CECI: mettez cette partie du code quelque part mais pas dans la méthode onCreate d'activité

public void LoadTable (chaîne finale u, chaîne finale k) {

    //  runOnUiThread need to be used or error will appear 
    new AsyncTask<Void, Void, Void>() {
        @Override
        protected Void doInBackground(Void... params) {
            try {

                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                       //method which was problematic and was casing a problem
                       createTable(u, k);
                    }
                });
            } catch (Exception exception) {
                createAndShowDialog(exception, "Error");
            }
            return null;
        }
    }.execute();
}
0
Jevgenij Kononov

Essaye ça:

textView.post(new Runnable() {
    @Override
    public void run() {
    textView.setText("Hello!"); }
});
0
frapeti