我正在 Android 中实现 REST 客户端。 我见过一个使用
Service
执行与服务器的连接并使用 ResultReceiver
来通知操作完成的示例。我正在从片段调用服务,如果我尝试在服务运行时旋转屏幕,ResultReceiver
中的 getActivity() 方法将返回 null,因为该片段可能不再处于布局中。
fragment中的回调方法:
@Override
public void onReceiveResult(int resultCode, Bundle resultData) {
Response response = (Response) resultData
.getSerializable(RestService.RESULT);
if (resultCode == RestService.SUCCESS
&& response != null) {
if (getActivity() != null) {
recommendationResponse = response;
getLoaderManager().restartLoader(0, new Bundle(),
Fragment.this);
}
}
}
getActivity()
返回 null。
这是正常的吗?我可以使用什么方法来允许在屏幕旋转时发出通知?本地广播?
不,
android:configChanges="orientation"
不是解决方案。
使用 ResultReceiver I:
保存方向变化:
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putParcelable(Consts.RECEIVER, mReceiver);
super.onSaveInstanceState(outState);
}
重置接收器:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (savedInstanceState != null) {
mReceiver = savedInstanceState.getParcelable(Consts.RECEIVER);
}
else {
mReceiver = new MyResultReceiver(new Handler());
}
mReceiver.setReceiver(this);
}
这是我的 ResultReceiver 类:
import android.os.Bundle;
import android.os.Handler;
import android.os.ResultReceiver;
public class MyResultReceiver extends ResultReceiver {
private Receiver mReceiver;
public MyResultReceiver(Handler handler) {
super(handler);
}
public void setReceiver(Receiver receiver) {
mReceiver = receiver;
}
public interface Receiver {
public void onReceiveResult(int command, Bundle resultData);
}
@Override
protected void onReceiveResult(int command, Bundle resultData) {
if (mReceiver != null) {
mReceiver.onReceiveResult(command, resultData);
}
}
}
我正在使用使用
BroadcastReceiver
注册的 LocalBroadcastManager
并且它工作正常。事情没那么简单。有更好的解决方案吗?
我想我偶然发现了同样的问题,并通过在 ResultReceiver 的 onReceivedResult 方法中验证 NULL 来解决它。此处发布的代码适用于工作人员片段(没有 UI 的片段和 onCreate 中的 setRetainInstance(true) )
protected void onReceiveResult(int resultCode, Bundle resultData) {
//Verify activity
if(getActivity() != null){
//Handle result
}else{
notificationPending = true;
}
}
notificationPending 标志可帮助片段在未找到活动时保留待处理的通知(活动在片段分离上不可用)。
当片段重新附加到活动时,我执行此逻辑
public void onAttach(Activity activity){
super.onAttach(activity);
if(notificationPending){
//Handle notification
notificationPending = false;
}
}
希望有帮助。如果您愿意,可以询问更多详细信息。干杯
是的,这很正常,因为 ResultReceiver 可能是“无头”的。
我尝试将
ResultReceiver
保存在 onSaveInstanceState()
处,但它不起作用,因为更新是在接收 Fragment
被破坏时发生的,丢失了,而且对回调的引用也被破坏了。
可以在这里找到解释和可能的解决方案:https://stanmots.blogspot.com/2016/10/androids-bad-company-intentservice.html
关于这个问题的另一篇好读物: https://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html
如何使用
ResultReceiver
的完整解决方案可以在这里找到:
https://stackoverflow.com/a/54334864/6747171
就我而言,找到了另一种有效的方法,也许它也会对某人有帮助
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);//add this line
}
getActivity() 返回 null。这正常吗?
Android 活动在设备旋转后重新创建。
重新创建活动后,它不会保留旧的上下文。这就是为什么你的
getActivity()
为 null
我可以使用什么方法来允许屏幕上的通知 回转?本地广播?
如果您不想在屏幕旋转上重新创建 Activity。请在清单中提及以下内容
<activity
android:name=".MyActivity"
android:configChanges="orientation" <<<<<<<<<
android:label="@string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
最后您必须覆盖 Activity 中的以下内容。
@Override
public void onConfigurationChanged(Configuration newConfig)
{
// TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
}