私のアプリには、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);
このエラーは、UIスレッドではないスレッドからUI要素にアクセスしようとしたときに発生します。
非UIスレッドの要素にアクセス/変更するには、runOnUIThread
を使用します。
ただし、fragment
内からUI要素を変更する必要があるため、アクティビティを所有するフラグメントに対して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.
_
詳細については、次のドキュメントを参照してください。
runOnUIThread()
関数を使用する必要があります。見つけたときに投稿するサンプルがあります。
タイマーに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);
}
});
}
別のスレッドからUI操作を実行しています。以下を使用することをお勧めします。
runOnUiThread(new Runnable() {
@Override
public void run() {
kiir.setText(ki_adat);
}
2つのソリューション:
Runnable
オブジェクトの run() メソッドにmyTextView.setText(str)
呼び出しを配置します。
これを試してください:アクティビティのonCreateメソッドではなく、コードのこの部分をどこかに置きます
public void LoadTable(最終文字列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();
}
これを試して:
textView.post(new Runnable() {
@Override
public void run() {
textView.setText("Hello!"); }
});