Android 如果从片段使用,则GoogleAppClient未连接

Android 如果从片段使用,则GoogleAppClient未连接,android,google-signin,Android,Google Signin,我今天发现了一种奇怪的行为 我的活动连接到onStart()中的GoogleAppClient,并在onStop()中断开连接 该活动使用GridViewPager显示我的片段。为了通过数据层发送消息,我在activity和fragment之间使用回调接口 如果我从活动布局中的按钮调用sendMessage(),它可以正常工作。如果片段使用回调接口执行sendMessage(),sendMessage()将显示“未连接”Toast 在这两种方式中,都会调用活动中的相同方法,那么它的行为如何可能不

我今天发现了一种奇怪的行为

我的活动连接到onStart()中的GoogleAppClient,并在onStop()中断开连接

该活动使用GridViewPager显示我的片段。为了通过数据层发送消息,我在activity和fragment之间使用回调接口

如果我从活动布局中的按钮调用sendMessage(),它可以正常工作。如果片段使用回调接口执行sendMessage(),sendMessage()将显示“未连接”Toast

在这两种方式中,都会调用活动中的相同方法,那么它的行为如何可能不同呢

我应该提到,这个问题只有在应用程序第一次重新启动后才会出现

活动

public class WearPlex extends WearableActivity implements
    NavigationRemoteCallbacks,
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener {

private List<Node> nodeList = new ArrayList<Node>();
private List<Fragment> fragmentList = new ArrayList<Fragment>();
private GoogleApiClient googleApiClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_wear_plex);
    setAmbientEnabled();

    fragmentList.add(NavigationRemoteFragment.getInstance(this));

    GridViewPager mGridPager = (GridViewPager)findViewById(R.id.gridViewPager);
    mGridPager.setAdapter(new MainGridPageAdapter(getFragmentManager(), fragmentList));

    googleApiClient = new GoogleApiClient.Builder(this)
            .addApi(Wearable.API)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();
}

@Override
protected void onStart() {
    super.onStart();
    googleApiClient.connect();
}

@Override
protected void onStop() {
    googleApiClient.disconnect();
    super.onStop();
}

@Override
public void onConnected(Bundle bundle) {
    Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();

    nodeList.clear();
    Wearable.NodeApi.getConnectedNodes(googleApiClient).setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() {
        @Override
        public void onResult(NodeApi.GetConnectedNodesResult nodes) {
            for (Node node : nodes.getNodes()) nodeList.add(node);
        }
    });
}

@Override
public void navigationRemoteSendCommand(String commandPath) {
    sendMessage(commandPath, null);
}

public void debugOnClick(View view) {
    sendMessage("/debug", null);
}

public void sendMessage(String path, byte[] data) {
    if (googleApiClient.isConnected()) {
        for (int i = 0; i < nodeList.size(); i++) {
            if (nodeList.get(i).isNearby()) {
                Toast.makeText(this, "Send message", Toast.LENGTH_SHORT).show();
                Wearable.MessageApi.sendMessage(googleApiClient, nodeList.get(i).getId(), path, data);
            }
        }
    } else {
        Toast.makeText(this, "Not connected", Toast.LENGTH_SHORT).show();
    }
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    Toast.makeText(this, "Connection failed", Toast.LENGTH_SHORT).show();
}
}

回调接口

public interface NavigationRemoteCallbacks {
    public void navigationRemoteSendCommand(String commandPath);
}
编辑MainGridPageAdapter的1个代码

public class MainGridPageAdapter extends FragmentGridPagerAdapter {

private List<Fragment> fragmentList = null;

public MainGridPageAdapter(FragmentManager fm, List<Fragment> fragmentList) {
    super(fm);
    this.fragmentList = fragmentList;
}

@Override
public Fragment getFragment(int i, int i1) {
    if (i1 < fragmentList.size()) return fragmentList.get(i1);
    return null;
}

@Override
public int getRowCount() {
    return 1;
}

@Override
public int getColumnCount(int i) {
    return fragmentList.size();
}
public类MainGridPageAdapter扩展了FragmentGridPagerAdapter{
私有列表fragmentList=null;
公共MainGridPageAdapter(FragmentManager fm,列表fragmentList){
超级(fm);
this.fragmentList=碎片列表;
}
@凌驾
公共片段getFragment(inti,inti1){
if(i1
您没有显示
MainGridPageAdapter
的代码,因此我不知道它是如何管理片段的。您提到问题发生在重新启动后。查看
WearPlex.onCreate()中的代码
,我怀疑问题是由包含对旧的、已销毁的活动实例的引用的片段引起的

FragmentManager
的一个记录不充分的行为是,它会在重新启动时保存其状态。这经常被忽略,导致重新启动后出现重复的片段实例。在主机活动的
onCreate()
方法中管理片段创建的正确模式是:

    if (savedInstanceState == null) {
        // Not a restart
        // Create a new instance of the fragment
        // Add it to the fragment manager
    } else {
        // Restart
        // The fragment manager has saved and restored the fragment instances
        // Use findFragmentById() to get the fragment if you need it
    }
您没有在
onCreate()中使用
savedInstanceState
测试是否重新启动。重新启动后是否看到比预期更多的片段?如果是,则原始片段包含对旧活动的引用,该活动已停止,并且具有断开连接的GoogleAppClient。如果单击其中一个片段的NavBtn,您将看到“未连接”toast

更新

该问题是由创建
NavigationRemoteFragment
的新实例的方式引起的,特别是使用static成员
NavigationRemoteFragment
。重新启动后,当重新创建活动时,代码调用
NavigationRemoteFragment.getInstance(this)
getInstance()
发现
navigationRemoteFragment
不为null,因为它是静态的,并且不创建新的片段。返回的片段是旧片段,它包含对旧活动的引用,该活动已停止,并且具有断开连接的
GoogleAppClient

这可以通过使用该方法并添加调试日志来确认:

@Override
public void navigationRemoteSendCommand(String commandPath) {
    if (isDestroyed()) {
        Log.w("TEST", "This is an old instance of the activity");
    }
    sendMessage(commandPath, null);
}

首先感谢您的快速响应。我在第一篇文章中附加了
MainGridPageAdapter
。如果我从
onCreate()中调用
getFragmentManager().getbackbackbackentrycount()
重新启动应用程序后,总是
0
。我认为片段管理器中没有多个片段实例,因为GridViewPager只显示一个片段。
@Override
public void navigationRemoteSendCommand(String commandPath) {
    if (isDestroyed()) {
        Log.w("TEST", "This is an old instance of the activity");
    }
    sendMessage(commandPath, null);
}