Java Android“只有创建视图层次结构的原始线程才能触及其视图。” 片段错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18656813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android "Only the original thread that created a view hierarchy can touch its views." error in Fragment
提问by David
I've got this simple timer in my app which is runs in every 3 seconds. It works perfectly if it's not in a fragment class. But here in fragment I always got the error: Only the original thread that created a view hierarchy can touch its views.
我的应用程序中有这个简单的计时器,每 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) {
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);
采纳答案by matthewrdev
This error occurs when trying to access UI elements from any thread that is not the UI thread.
尝试从非 UI 线程的任何线程访问 UI 元素时会发生此错误。
To access/modify elements from a non-UI-thread, use runOnUIThread
.
要从非 UI 线程访问/修改元素,请使用runOnUIThread
.
However as you need to change a UI element from within a fragment
, runOnUIThread
should be invoked onto the fragments owning activity. You can do this through getActivity().runOnUIThread()
.
但是,当您需要从 中更改 UI 元素时fragment
,runOnUIThread
应在拥有活动的片段上调用 , 。您可以通过getActivity().runOnUIThread()
.
EG:
例如:
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.
For further information see the following documentation:
有关更多信息,请参阅以下文档:
回答by Cob50nm
you need to use the runOnUIThread()
function I have an example somwhere that I will post when I find it.
你需要使用runOnUIThread()
我有一个例子的功能,当我找到它时我会发布它。
you need to give your timer an instance of MainActivity alternatively see this question I asked Android image timing issueswith what sounds like a similar thing to what you were trying to do
你需要给你的计时器一个 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);
}
});
}
回答by Ritesh Gune
You are doing UI operation from another thread. I suggest you to use following.
您正在从另一个线程进行 UI 操作。我建议你使用以下。
runOnUiThread(new Runnable() {
@Override
public void run() {
kiir.setText(ki_adat);
}
回答by Girish Nair
Try this
尝试这个
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();
回答by flawyte
2 solutions :
2个解决方案:
- Use the View.post(Runnable)method
- Use the Activity.post(Runnable)method
And put the myTextView.setText(str)
call in the run()method of the Runnable
object.
并将myTextView.setText(str)
调用放在对象的run()方法中Runnable
。
回答by Jevgenij Kononov
TRY THIS: put this part of code somewhere but not in activity onCreate method
试试这个:把这部分代码放在某个地方,但不要放在 onCreate 方法的活动中
public void LoadTable(final String u, final String k) {
公共无效负载表(最终字符串 u,最终字符串 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();
}
回答by frapeti
Try this:
尝试这个:
textView.post(new Runnable() {
@Override
public void run() {
textView.setText("Hello!"); }
});