ResultReceiver 无法适应屏幕旋转

问题描述 投票:0回答:6

我正在 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 rest service
6个回答
13
投票

不,

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);
        }
    }
}

1
投票

我正在使用使用

BroadcastReceiver
注册的
LocalBroadcastManager
并且它工作正常。事情没那么简单。有更好的解决方案吗?


1
投票

我想我偶然发现了同样的问题,并通过在 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;
        }
}

希望有帮助。如果您愿意,可以询问更多详细信息。干杯


0
投票

是的,这很正常,因为 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


0
投票

就我而言,找到了另一种有效的方法,也许它也会对某人有帮助

  @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);//add this line

        
    }

-1
投票

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);
    }
© www.soinside.com 2019 - 2024. All rights reserved.