英文:
Android: SetText in handler doesn't change text in TextView
问题
我有一个连接到蓝牙并显示接收到的信息的应用程序。
在按下返回键时,活动并没有被销毁,我可以返回到该活动,并且一切都保持不变。该活动在后台收集数据,一切正常。
我有一个按钮,当按下时,会销毁所有活动(包括显示数据的活动)。
当我尝试再次创建该活动时,数据继续到达,我仍然可以处理它并将其写入文件,但在用户界面中不会显示出来。似乎在第二次创建活动后,处理程序中的setText函数不起作用(在处理程序之外的地方setText确实起作用)。
布尔值synced
在活动第二次创建时为true。
这是OnCreate
方法:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_admin);
loading_panel = findViewById(R.id.loadingPanel);
loading_panel.setVisibility(View.GONE);
connectionButton = (Button) findViewById(R.id.connection_button);
gsrTextView = (TextView) findViewById(R.id.gsr_textview);
emgTextView = (TextView) findViewById(R.id.emg_textview);
adxlTextView = (TextView) findViewById(R.id.adxl_textview);
fsrTextView = (TextView) findViewById(R.id.fsr_textview);
textviews_set=true;
if(synced)
{
setConnected(currMac);
manageConnection();
Button sync_button = (Button) findViewById(R.id.sync_button);
sync_button.setText(R.string.synced_text);
}
// 更多的代码
}
OnBackPressed
方法的实现:
@Override
public void onBackPressed() {
Intent i = new Intent(AdminActivity.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(i);
}
这是处理程序的一部分:
@SuppressLint("HandlerLeak")
public final Handler handler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what) {
// 其他情况的大量代码
case READ_SUCCESS:
String s = (String) msg.obj;
showData(s);
break;
}
}
};
这是showData
的一部分:
private void showData(String s) {
// 待办事项:1.解析JSON;2.在TextView上显示数据(JSON组件)
try {
//Log.d(LOG_TAG, "the new string is " + s);
JSONObject json = new JSONObject(s);
// 收集传感器测量值
String gsrMeasure = json.getString("gsr");
String emgMeasure = json.getString("emg");
String adxlMeasure = json.getString("adxl");
String fsrMeasure = json.getString("fsr");
String time_str = json.getString("time");
// 显示数据
if(textviews_set) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d(LOG_TAG, "ABOUT TO SET TEXT");
gsrTextView.setText(gsrMeasure);
emgTextView.setText(emgMeasure);
adxlTextView.setText(adxlMeasure);
fsrTextView.setText(fsrMeasure);
}
});
}
// 更多的代码
} catch (JSONException e) {
e.printStackTrace();
}
}
我甚至确保在UI线程上运行setText,尽管在第一次运行活动时没有使用runOnUiThread
。我还认为可能是在findViewByID
调用之前处理程序被调用,但我使用了一个名为textviews_set
的布尔变量来确保它不会发生。
值得一提的是,当我第一次创建活动时,蓝牙设备未连接,因此处理程序未运行,因此问题很有可能出在这里。 我只是不确定确切的位置,或者如何解决它。
英文:
I have an app that connects to bluetooth and displays information received.
when pressing back, the activity isn't killed and I can go back to the activity and everything is the same. The activity collects the data in the background and everything is okay
I have a button, that when pressed, kills all activities (including the activity that displays the data).
When I try to create that activity again, the data keeps coming, and I can still handle it and write it to a file, but it won't show it in the UI. It seems the setText function in the handler doesn't work after the activity is created the second time (setText does work outside of the handler).
The boolean value synced
is true if the activity is created a second time.
This is OnCreate
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_admin);
loading_panel = findViewById(R.id.loadingPanel);
loading_panel.setVisibility(View.GONE);
connectionButton = (Button) findViewById(R.id.connection_button);
gsrTextView = (TextView) findViewById(R.id.gsr_textview);
emgTextView = (TextView) findViewById(R.id.emg_textview);
adxlTextView = (TextView) findViewById(R.id.adxl_textview);
fsrTextView = (TextView) findViewById(R.id.fsr_textview);
textviews_set=true;
if(synced)
{
setConnected(currMac);
manageConnection();
Button sync_button = (Button) findViewById(R.id.sync_button);
sync_button.setText(R.string.synced_text);
}
// more code
}
Implementation of OnBackPressed
:
@Override
public void onBackPressed() {
Intent i = new Intent(AdminActivity.this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(i);
}
This is (part of) the handler:
@SuppressLint("HandlerLeak")
public final Handler handler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
switch (msg.what) {
//a lot of code for other cases
case READ_SUCCESS:
String s = (String) msg.obj;
showData(s);
break;
}
}
}
This is (part of) showData
:
private void showData(String s) {
// todo: 1.parse the json; 2.show data (json components) on the textViews
try {
//Log.d(LOG_TAG, "the new string is " + s);
JSONObject json = new JSONObject(s);
// Collect the sensors measurements
String gsrMeasure = json.getString("gsr");
String emgMeasure = json.getString("emg");
String adxlMeasure = json.getString("adxl");
String fsrMeasure = json.getString("fsr");
String time_str = json.getString("time");
// Show the data
if(textviews_set) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d(LOG_TAG, "ABOUT TO SET TEXT");
gsrTextView.setText(gsrMeasure);
emgTextView.setText(emgMeasure);
adxlTextView.setText(adxlMeasure);
fsrTextView.setText(fsrMeasure);
}
});
}
//more code
}
}
I even made sure that I'm running the setText on UI thread even though it works on the first run of the activity without the runOnUiThread
I also thought that maybe the handler is called before the findViewByID
s are called but I used a boolean variable textviews_set
to make sure it doesn't happen
It is worth mentioning that when I create the activity for the first time, the bluetooth device isn't connected and thus the handler isn't running, so there's a really good chance that the problem lies there. I just don't know exactly where, or how to solve it.
答案1
得分: 1
我找出了问题所在,如果有人遇到同样的问题。我将所有的TextView声明为非静态的,因此当第二次创建活动时,由于某种原因处理程序仍然引用第一个实例活动的TextView。
我所需要做的就是将类中的TextView声明为static
,这样当我第二次创建活动时,这些TextView已经被声明并且引用了XML中的实际TextView。
英文:
I found out what the problem was, if anyone gets stuck with the same issue.
I declared all the textviews as non-static, thus when creating the activity the second time, for some reason the handler still referred to the textviews of the first instance of the activity.
All I had to do was declare the textviews in the class as static
, so when I create the activity for the second time, the textviews are already declared and refer to the actual textviews in the xml.
答案2
得分: 0
根据提供的信息,以下是最佳建议。
所以在 onCreate()
中尝试在 textviews_set=true;
之前执行以下操作:
gsrTextView.setText(" ");
emgTextView.setText(" ");
adxlTextView.setText(" ");
fsrTextView.setText(" ");
希望这能解决问题。
参考:
英文:
Based on the information provide the follow is the best suggestion.
So try the following in onCreate()
before textviews_set=true;
gsrTextView.setText(" ");
emgTextView.setText(" ");
adxlTextView.setText(" ");
fsrTextView.setText(" ");
Hope this solves issue.
Reference:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论