Android片段附加runnable

时间:2016-03-01 21:28:59

标签: android multithreading android-fragments runnable android-handler

我有一个包含处理程序和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);
    }
}

... 
}

1 个答案:

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