GoogleApiClient not connected if used from fragment

Today I discovered strange behavior.

I have my activity that connects to GoogleApiClient in onStart () and disconnects in onStop ()

Activity uses GridViewPager to display my fragments. To send messages through the data layer, I use the callback interface between activity and fragment.

If I call sendMessage () from a button in the Activity layout, it works fine. If sendMessage () is executed by a fragment using the callback interface, sendMessage () shows a Toast not connected.

In both cases, the same method in the Activity is called so, how is it possible that it behaves differently?

I should mention that the problem only occurs after restarting the application for the first time.

Activities

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

Fragment

public class NavigationRemoteFragment extends Fragment {

private static NavigationRemoteFragment navigationRemoteFragment = null;

private NavigationRemoteCallbacks callbackHandler = null;

private ImageButton navBtnCenter;

public static NavigationRemoteFragment getInstance(NavigationRemoteCallbacks handler) {
    if (navigationRemoteFragment == null) {
        navigationRemoteFragment = new NavigationRemoteFragment();
        navigationRemoteFragment.callbackHandler = handler;
    }

    return navigationRemoteFragment;
}

public NavigationRemoteFragment() {
    // Required empty public constructor
}

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

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View v = inflater.inflate(R.layout.fragment_navigation_remote, container, false);

    navBtnCenter = (ImageButton)v.findViewById(R.id.navBtnCenter);

    navBtnCenter.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            callbackHandler.navigationRemoteSendCommand("/debug");
        }
    });

    return v;
}

}

Callback interface

public interface NavigationRemoteCallbacks {
    public void navigationRemoteSendCommand(String commandPath);
}

EDIT 1 Code for MainGridPageAdapter

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();
}
+4
source share
1 answer

You do not show the code for MainGridPageAdapter, so I do not know how it manages the fragments. You note that the problem occurs after a reboot. Looking at the code in WearPlex.onCreate(), I suspect that the problem is caused by fragments that contain a link to an old, destroyed instance of the action.

A poorly documented behavior FragmentManageris that it retains its state through reboots. This is often overlooked, resulting in duplicate instances of the fragment after a restart. The correct template for controlling fragment creation in the onCreate()host activity method :

    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
    }

savedInstanceState onCreate(), . , ? , , ​​ GoogleApiClient. NavBtn , " " .

, NavigationRemoteFragment, , static NavigationRemoteFragment. , , NavigationRemoteFragment.getInstance(this). getInstance() NavigationRemoteFragment null, . , , ​​ GoogleApiClient.

isDestroyed :

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

Source: https://habr.com/ru/post/1618488/


All Articles