2015-12-03 68 views
4

今天我發現了一個奇怪的行爲。GoogleApiClient沒有連接,如果從片段使用

我在的onStop()

活動使用GridViewPager顯示我的片段,我的活動它連接到GoogleApiClient在在onStart()和斷開。要通過數據層發送消息,我使用活動和片段之間的回調接口。

如果我從活動佈局中的按鈕調用sendMessage()它工作正常。如果sendMessage()由使用回調接口的片段執行,則sendMessage()顯示「未連接」的Toast。

在兩種方式中,調用Activity中的同一個方法,所以它的行爲有什麼不同?

我應該提到,該問題僅在第一次重新啓動應用程序後纔會發生。

活動

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

}

回調接口

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

EDIT 1 MainGridPageAdapter

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

回答

1

您不顯示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來測試重新啓動。你重啓後是否看到比預期更多的碎片?如果是這樣,原始片段將保留對舊活動的引用,該活動已停止,並且已斷開連接的GoogleApiClient。如果其中一個片段的NavBtn被點擊,您將看到「未連接」的吐司。

問題是由的方式造成更新要創建的NavigationRemoteFragment新的情況,尤其是使用靜態成員navigationRemoteFragment的。重新啓動後,當活動重新創建時,代碼將調用NavigationRemoteFragment.getInstance(this)getInstance()發現navigationRemoteFragment非空,因爲它是靜態的,並且不會創建新的片段。返回的片段是舊片段,它保存對舊活動的引用,該舊活動已停止並且具有斷開的GoogleApiClient

這可以通過使用isDestroyed方法並增加了一些調試日誌記錄進行確認:

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

承滴盤首先感謝您的快速響應。我在第一篇文章中附加了「MainGridPageAdapter」。如果我從'onCreate()'中調用'getFragmentManager()。getBackStackEntryCount()',那麼在重新啓動應用程序後它總是'0'。我不認爲片段管理器中有多個片段實例,因爲GridViewPager只顯示一個片段。 –

+0

解決了問題,謝謝 –

相關問題