我有一个包含处理程序和runnable的片段。当显示片段时,处理程序调用runnable,其中callback是处理程序。从runnable我更新视图。
这可以按我的意愿运作。
以下是我遇到问题的情况:
当我打开另一个应用程序(如文本消息或其他东西)然后我回到我的应用程序时,片段视图被重新创建并且runnable不再更新视图(当我首先离开我的应用程序时,runnable仍在运行)。
我已经查看了片段生命周期,并且读取了片段必须显示时始终调用onCreateView方法。但在我的情况下,这会创建一个新视图,而不是runnable正在更新的视图。
那么当我回到我的应用程序时,如何让runnable仍然更新视图?
以下是片段的代码:
public class RecordingFragment extends Fragment {
private Handler mHandler;
private TextView speedTextView;
private TextView rmpTextView;
/**
* Thread that sends commands to OBD
*/
private final Runnable runnable = new Runnable() {
@Override
public void run() {
notifcationBuilder.setProgress(0, 0, true);
notificationManager.notify(notificationId, notifcationBuilder.build());
data = sendCommandsToOdb(mSocket);
// Show data in UI
if (data.get("Vehicle Speed") != null) {
speedTextView.setText(data.get("Vehicle Speed").toString());
}
if (data.get("Engine RPM") != null) {
rmpTextView.setText(data.get("Engine RPM").toString());
}
mHandler.postDelayed(this, 1000);
}
};
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_obd_recording, container, false);
speedTextView = (TextView) view.findViewById(R.id.speedTextView);
rmpTextView = (TextView) view.findViewById(R.id.rpmTextView);
...
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// TODO : Refactor this with save instance
// Récupération depuis les preferences
handlerRunning = preferences.getBooleanValue("isHandlerRunning");
if (!handlerRunning) {
mHandler = new Handler();
handlerRunning = true;
preferences.saveBoolean("isHandlerRunning", handlerRunning);
openDeviceConnection(device);
}
}
...
}
答案 0 :(得分:0)
您可以在创建视图后让您的片段保留setRetainInstance(true)
或更好地运行您的runnable - 来自onActivityCreated()
回调
保持对不同类中的视图的引用(您的Runnable实现)并不是一个好主意。更好的架构是Runnable不会直接修改视图
---代码共享后编辑---
对于这个具体的问题,您可以使用AsyncTask,它可以处理后台线程以进行持久操作,然后将更新发布到UI线程。但即便如此,你仍然可能泄露你的观点,你不应该这样做。最简单的解决方案是在更新视图之前检查活动是否仍然存在,如果没有则丢弃更改,然后保留Fragment。我还要补充一点,这不是我的首选解决方案,但要开始尝试,请尝试以下方法:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
new AsyncTask<Void, Void, Object>() {
@Override
protected void onPreExecute() {
notifcationBuilder.setProgress(0, 0, true);
notificationManager.notify(notificationId, notifcationBuilder.build());
}
@Override
protected Object doInBackground(Void... params) {
return sendCommandsToOdb(mSocket);;
}
@Override
protected void onPostExecute(Object data) {
Activity activity = getActivity();
if (activity == null || activity.isFinishing()){
return;
}
// Show data in UI
if (data.get("Vehicle Speed") != null) {
speedTextView.setText(data.get("Vehicle Speed").toString());
}
if (data.get("Engine RPM") != null) {
rmpTextView.setText(data.get("Engine RPM").toString());
}
}
}.execute();
}