2013-09-06 3 views
26

Mam prosty zegar w mojej aplikacji, który jest uruchamiany co 3 sekundy. Działa doskonale, jeśli nie znajduje się w klasie fragmentów. Ale tutaj w fragmencie zawsze mam błąd: tylko oryginalny wątek, który utworzył hierarchię widoku, może dotknąć jej widoków.Android "Tylko oryginalny wątek, który utworzył hierarchię widoku, może dotykać swoich widoków." błąd w Fragmentie

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); 

Odpowiedz

83

Ten błąd występuje podczas próby uzyskania dostępu do elementów interfejsu z dowolnego wątku, który nie jest wątkiem interfejsu użytkownika.

Aby uzyskać dostęp/modyfikować elementy z wątku innego niż UI, należy użyć runOnUIThread.

Jednak aby zmienić element interfejsu użytkownika z poziomu fragment, należy wywołać runOnUIThread na działce będącej właścicielem fragmentów. Możesz to zrobić przez getActivity().runOnUIThread().

np

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. 

Dalsze informacje można znaleźć w następujących dokumentów:

  1. Android Fragments (konkretnie getActivity()).
  2. TimerTask.
  3. Invoking a Runnable on the UI thread.
+0

thx! ale jak ustawić czas? – David

+1

Zgubiłeś mnie ... Gdzie próbujesz ustawić czas w swoim kodzie? – matthewrdev

+0

w ostatnim wierszu "}, 0, 3000);" oznacza to 3 sekundy – David

8

trzeba użyć funkcji runOnUIThread() Mam przykład somwhere że będę po, kiedy go znaleźć.

trzeba dać stoper wystąpienie główną działalność alternatywnie zobacz to pytanie zadałem Android image timing issues z tym, co brzmi jak coś podobnego do tego, co staraliśmy się zrobić

public static void updateText(Activity act, resID) 
{ 

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

        } 

       }); 
} 
+0

dziękuję! Jestem czekające :) – David

3

robisz operację UI z innego wątku . Proponuję użyć następującego.

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

        kiir.setText(ki_adat); 
       }     
+0

Sposób runOnUiThread (nowa Runnable() {}) jest zdefiniowana dla danego typu nowy TimerTask() {} – David

+0

użycie your_activity_name.runOnUiThread .. –

+0

Fragment1.this.runOnUiThread (nowa Runnable() { \t \t \t \t \t \t \t @Override \t \t \t \t \t \t \t public void run() { \t \t \t \t \t \t \t \t // Ten kod będzie zawsze uruchamiane na wątków UI, \t \t \t \t \t \t \t \t // dlatego jest bezpieczny modyfikować elementy interfejsu użytkownika. \t \t \t \t \t \t \t \t System.out.println ("FAszom"); \t \t \t \t \t \t \t \t kiir.setText ("mój tekst"); \t \t \t \t \t \t \t} \t \t \t \t \t \t}); Ten sam błąd i zatrzymuje wirking – David

-1

Spróbuj tego

new CountDownTimer(365*24*60*60, 3000) { 

public void onTick(long millisUntilFinished) { 
    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) { 
        // TODO Auto-generated catch block 
        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) { 
        // TODO Auto-generated catch block 
        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) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } catch (ModbusSlaveException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } catch (ModbusException e) { 
        // TODO Auto-generated catch block 
        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 = ""; 
} 

public void onFinish() {} 
}.start(); 
+3

Oh cool, zagadka. Zobacz, ile czasu zajmuje znalezienie różnicy między odpowiedzią a oryginalnym kodem w pytaniu. Ironia wyłączona: -1 dla odpowiedzi tylko bez wyjaśnienia, co zostało zmienione i dlaczego. – WarrenFaith

0

Spróbuj to: umieścić tę część kodu gdzieś, ale nie w aktywności onCreate metoda

public void LoadTable (final String u, final String 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

Spróbuj:

textView.post(new Runnable() { 
    @Override 
    public void run() { 
    textView.setText("Hello!"); } 
}); 
Powiązane problemy