Android «Только исходный поток, создавший иерархию представлений, может коснуться его представлений». Error in Fragment

Привет, у меня этот простой таймер в моем приложении, который запускается каждые 3 секунды. Он отлично работает, если он не находится в классе фрагментов. Но здесь, в фрагменте, я всегда получал ошибку: только исходный поток, создавший иерархию представлений, может коснуться его представлений. Пожалуйста, помогите мне, как исправить это! Спасибо вам, ребята!

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) { // 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 = ""; }//run vége }, 0, 3000); 

Solutions Collecting From Web of "Android «Только исходный поток, создавший иерархию представлений, может коснуться его представлений». Error in Fragment"

Эта ошибка возникает при попытке доступа к элементам пользовательского интерфейса из любого потока, который не является потоком пользовательского интерфейса.

Для доступа / изменения элементов из не-UI-потока используйте runOnUIThread .

Однако, поскольку вам нужно изменить элемент пользовательского интерфейса изнутри fragment , runOnUIThread должен быть вызван на активность, runOnUIThread с фрагментами. Вы можете сделать это через getActivity().runOnUIThread() .

НАПРИМЕР:

 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. 

Для получения дополнительной информации см. Следующую документацию:

  1. Android Fragments (в частности, getActivity() ).
  2. TimerTask .
  3. Вызов Runnable в потоке пользовательского интерфейса.

Вам нужно использовать runOnUIThread() У меня есть пример somwhere, который я опубликую, когда найду его.

Вам нужно предоставить вашему таймеру экземпляр MainActivity, альтернативно, увидеть этот вопрос. Я задал вопросы о синхронизации изображений Android с тем, что похоже на то, что вы пытались сделать

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

Вы выполняете операцию пользовательского интерфейса из другого потока. Я предлагаю вам использовать следующее.

 runOnUiThread(new Runnable() { @Override public void run() { kiir.setText(ki_adat); } 

2 решения:

  • Использовать метод View.post (Runnable)
  • Используйте метод Activity.post (Runnable)

И поместите myTextView.setText(str) в метод run () объекта Runnable .

ПОПРОБУЙТЕ ЭТО: поместите эту часть кода где-нибудь, но не в действие onCreate method

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

Попробуй это:

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

Попробуй это

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