Android返回activity后服务挂起
Android Service hanging after returning to the activity
我觉得这个问题很有趣,有些人可能不感兴趣。希望我能得到一个可靠的答案。
我有一个Fragment,它在onResume()
中绑定了一个服务,当用户在场时每60秒自动刷新一次数据。我的 bind()
方法在这里...
public void bind() {
if(connected || MainActivity.sRefresherBinding) return;
MainActivity.sRefresherBinding = true;
Log.v(LOG_TAG, "binding...");
mProgressDialog.setTitle("Service Connected!");
mProgressDialog.setMessage("We're almost there!");
Intent bindingIntent = new Intent(getActivity(), Refresh.class);
getActivity().bindService(bindingIntent, mConnection, Context.BIND_AUTO_CREATE);
getActivity().startService(bindingIntent);
}
这里调用了对应的unbind()
方法onStop()
...
public void unbind() {
Log.v(LOG_TAG, "unbinding");
if (connected) {
mRefreshService.terminate();
getActivity().unbindService(mConnection);
getActivity().stopService(new Intent(getActivity(), Refresh.class));
connected = false;
}
}
onServiceConnected()
这里...
public void onServiceConnected(ComponentName name, IBinder service) {
if(binder != null) binder = null;
binder = (Refresh.LocalBinder) service;
if(mRefreshService != null) mRefreshService.terminate();
mRefreshService = binder.getService();
connected = true;
mProgressDialog.setTitle("Refreshing your data...");
mProgressDialog.setMessage("We are almost there!");
Log.v(LOG_TAG, "Service Connected");
}
我的 onStartCommand()
刷新扩展服务
public int onStartCommand(Intent intent, int flags, int startId) {
start(new UpdateListener() {
@Override
public void onUpdate(ArrayList<Quote.SingleQuote> newData) {
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(Utility.BROADCAST);
broadcastIntent.putExtra(Utility.QUOTE_INTENT, newData);
sendBroadcast(broadcastIntent);
}
});
if (mHandler == null) {
mHandler = new Handler();
mHandler.post(mRunnable);
}
return Service.START_STICKY;
}
运行能够...
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
refreshMain();
if (mHandler != null)
mHandler.postDelayed(this, MIN_UPDATE_TIME);
}
};
refreshMain 太大,我只 post 将结果发送回侦听器的片段...
call.enqueue(new Callback<Quote>() {
@Override
public void onResponse(Response<Quote> response) {
try {
List<Quote.SingleQuote> asList = response.body().query.results.getQuote();
mQuotes = new ArrayList<>(asList);
mListener.onUpdate(mQuotes);
Log.v(LOG_TAG, "Refreshed");
}
最后是我的广播接收器...
public static class UpdateReceiver extends BroadcastReceiver{
@Override
public void onReceive(final Context context, final Intent intent) {
if(MainFragmentService.getInstance().mProgressDialog != null) MainFragmentService.getInstance().mProgressDialog.dismiss();
if(MainFragmentService.getInstance() != null) {
MainFragmentService.getInstance().mQuotes = intent.getParcelableArrayListExtra(Utility.QUOTE_INTENT);
MainFragmentService.getInstance().mAdapter.swapList(MainFragmentService.getInstance().mQuotes);
Log.v(LOG_TAG, "Package received");
MainActivity.sRefresherBinding = false;
}
}
}
这是棘手的部分。
所有这些代码在我的 Nexus 5 上运行得很好,但是当我 运行 它在我的 Nexus 7 上时,进入另一个 Activity 并返回,服务挂起。数据被获取、广播、拾取,但对话框没有被关闭,数据也没有显示在回收站视图中。
看看我的 Nexus 5 上的 logcat:
V/MainFragmentService: onPause
V/MainFragmentService: unbinding
V/MainFragmentService: onStop
V/MainFragmentService: onResume
V/MainFragmentService: binding...
V/Refresh: RefreshMain called
V/MainFragmentService: Service Connected
V/Refresh: Refreshed
V/MainFragmentService: Package received
现在看看我的 Nexus 7 上的 logcat:
V/MainFragmentService: onPause
V/MainFragmentService: unbinding
V/MainFragmentService: onStop
V/MainFragmentService: onResume
V/MainFragmentService: binding...
V/MainFragmentService: onResume
V/Refresh: RefreshMain called
V/MainFragmentService: Service Connected
V/Refresh: Refreshed
V/MainFragmentService: Package received
V/Refresh: Waiting
V/Refresh: Waiting
V/Refresh: RefreshMain called
V/Refresh: Refreshed
V/MainFragmentService: Package received
如果您对这段代码的工作有任何疑问,应用程序就在这里,去 nuts。如果您通读了这篇文章,感谢您的宝贵时间!
问题已追踪到开发者选项 > 应用 > 不要在 Nexus 7 上启用活动,在 Nexus 5(和其他)上禁用活动。
意味着真正的问题出在 Activity 本身,它在离开它时被摧毁了。返回时,会在现有片段之上创建一个新片段,因为我没有检查 savedInstanceState
。上面评论中提到的混乱现在也已修复,不再需要通过 Manifest 阻止 activity 对配置更改的破坏。
getFragmentManager().beginTransaction().add(R.id.content_main_list_container,
new MainFragmentService(), FRAGMENT_TAG_MAIN_LIST).commit();
现在是...
MainFragmentService mainFragment;
if(savedInstanceState == null) {
mainFragment = new MainFragmentService();
getFragmentManager()
.beginTransaction()
.add(R.id.content_main_list_container,
mainFragment, FRAGMENT_TAG_MAIN_LIST)
.commit();
}
我觉得这个问题很有趣,有些人可能不感兴趣。希望我能得到一个可靠的答案。
我有一个Fragment,它在onResume()
中绑定了一个服务,当用户在场时每60秒自动刷新一次数据。我的 bind()
方法在这里...
public void bind() {
if(connected || MainActivity.sRefresherBinding) return;
MainActivity.sRefresherBinding = true;
Log.v(LOG_TAG, "binding...");
mProgressDialog.setTitle("Service Connected!");
mProgressDialog.setMessage("We're almost there!");
Intent bindingIntent = new Intent(getActivity(), Refresh.class);
getActivity().bindService(bindingIntent, mConnection, Context.BIND_AUTO_CREATE);
getActivity().startService(bindingIntent);
}
这里调用了对应的unbind()
方法onStop()
...
public void unbind() {
Log.v(LOG_TAG, "unbinding");
if (connected) {
mRefreshService.terminate();
getActivity().unbindService(mConnection);
getActivity().stopService(new Intent(getActivity(), Refresh.class));
connected = false;
}
}
onServiceConnected()
这里...
public void onServiceConnected(ComponentName name, IBinder service) {
if(binder != null) binder = null;
binder = (Refresh.LocalBinder) service;
if(mRefreshService != null) mRefreshService.terminate();
mRefreshService = binder.getService();
connected = true;
mProgressDialog.setTitle("Refreshing your data...");
mProgressDialog.setMessage("We are almost there!");
Log.v(LOG_TAG, "Service Connected");
}
我的 onStartCommand()
刷新扩展服务
public int onStartCommand(Intent intent, int flags, int startId) {
start(new UpdateListener() {
@Override
public void onUpdate(ArrayList<Quote.SingleQuote> newData) {
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(Utility.BROADCAST);
broadcastIntent.putExtra(Utility.QUOTE_INTENT, newData);
sendBroadcast(broadcastIntent);
}
});
if (mHandler == null) {
mHandler = new Handler();
mHandler.post(mRunnable);
}
return Service.START_STICKY;
}
运行能够...
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
refreshMain();
if (mHandler != null)
mHandler.postDelayed(this, MIN_UPDATE_TIME);
}
};
refreshMain 太大,我只 post 将结果发送回侦听器的片段...
call.enqueue(new Callback<Quote>() {
@Override
public void onResponse(Response<Quote> response) {
try {
List<Quote.SingleQuote> asList = response.body().query.results.getQuote();
mQuotes = new ArrayList<>(asList);
mListener.onUpdate(mQuotes);
Log.v(LOG_TAG, "Refreshed");
}
最后是我的广播接收器...
public static class UpdateReceiver extends BroadcastReceiver{
@Override
public void onReceive(final Context context, final Intent intent) {
if(MainFragmentService.getInstance().mProgressDialog != null) MainFragmentService.getInstance().mProgressDialog.dismiss();
if(MainFragmentService.getInstance() != null) {
MainFragmentService.getInstance().mQuotes = intent.getParcelableArrayListExtra(Utility.QUOTE_INTENT);
MainFragmentService.getInstance().mAdapter.swapList(MainFragmentService.getInstance().mQuotes);
Log.v(LOG_TAG, "Package received");
MainActivity.sRefresherBinding = false;
}
}
}
这是棘手的部分。 所有这些代码在我的 Nexus 5 上运行得很好,但是当我 运行 它在我的 Nexus 7 上时,进入另一个 Activity 并返回,服务挂起。数据被获取、广播、拾取,但对话框没有被关闭,数据也没有显示在回收站视图中。
看看我的 Nexus 5 上的 logcat:
V/MainFragmentService: onPause
V/MainFragmentService: unbinding
V/MainFragmentService: onStop
V/MainFragmentService: onResume
V/MainFragmentService: binding...
V/Refresh: RefreshMain called
V/MainFragmentService: Service Connected
V/Refresh: Refreshed
V/MainFragmentService: Package received
现在看看我的 Nexus 7 上的 logcat:
V/MainFragmentService: onPause
V/MainFragmentService: unbinding
V/MainFragmentService: onStop
V/MainFragmentService: onResume
V/MainFragmentService: binding...
V/MainFragmentService: onResume
V/Refresh: RefreshMain called
V/MainFragmentService: Service Connected
V/Refresh: Refreshed
V/MainFragmentService: Package received
V/Refresh: Waiting
V/Refresh: Waiting
V/Refresh: RefreshMain called
V/Refresh: Refreshed
V/MainFragmentService: Package received
如果您对这段代码的工作有任何疑问,应用程序就在这里,去 nuts。如果您通读了这篇文章,感谢您的宝贵时间!
问题已追踪到开发者选项 > 应用 > 不要在 Nexus 7 上启用活动,在 Nexus 5(和其他)上禁用活动。
意味着真正的问题出在 Activity 本身,它在离开它时被摧毁了。返回时,会在现有片段之上创建一个新片段,因为我没有检查 savedInstanceState
。上面评论中提到的混乱现在也已修复,不再需要通过 Manifest 阻止 activity 对配置更改的破坏。
getFragmentManager().beginTransaction().add(R.id.content_main_list_container,
new MainFragmentService(), FRAGMENT_TAG_MAIN_LIST).commit();
现在是...
MainFragmentService mainFragment;
if(savedInstanceState == null) {
mainFragment = new MainFragmentService();
getFragmentManager()
.beginTransaction()
.add(R.id.content_main_list_container,
mainFragment, FRAGMENT_TAG_MAIN_LIST)
.commit();
}