我创建了一个小测试应用程序,它代表了我的问题。我使用ActionBarSherlock来用(Sherlock)片段实现选项卡。
我的代码:TestActivity.java
public class TestActivity extends SherlockFragmentActivity { private ActionBar actionBar; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setupTabs(savedInstanceState); } private void setupTabs(Bundle savedInstanceState) { actionBar = getSupportActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); addTab1(); addTab2(); } private void addTab1() { Tab tab1 = actionBar.newTab(); tab1.setTag("1"); String tabText = "1"; tab1.setText(tabText); tab1.setTabListener(new TabListener<MyFragment>(TestActivity.this, "1", MyFragment.class)); actionBar.addTab(tab1); } private void addTab2() { Tab tab1 = actionBar.newTab(); tab1.setTag("2"); String tabText = "2"; tab1.setText(tabText); tab1.setTabListener(new TabListener<MyFragment>(TestActivity.this, "2", MyFragment.class)); actionBar.addTab(tab1); } }
TabListener.java
public class TabListener<T extends SherlockFragment> implements com.actionbarsherlock.app.ActionBar.TabListener { private final SherlockFragmentActivity mActivity; private final String mTag; private final Class<T> mClass; public TabListener(SherlockFragmentActivity activity, String tag, Class<T> clz) { mActivity = activity; mTag = tag; mClass = clz; } /* The following are each of the ActionBar.TabListener callbacks */ public void onTabSelected(Tab tab, FragmentTransaction ft) { SherlockFragment preInitializedFragment = (SherlockFragment) mActivity.getSupportFragmentManager().findFragmentByTag(mTag); // Check if the fragment is already initialized if (preInitializedFragment == null) { // If not, instantiate and add it to the activity SherlockFragment mFragment = (SherlockFragment) SherlockFragment.instantiate(mActivity, mClass.getName()); ft.add(android.R.id.content, mFragment, mTag); } else { ft.attach(preInitializedFragment); } } public void onTabUnselected(Tab tab, FragmentTransaction ft) { SherlockFragment preInitializedFragment = (SherlockFragment) mActivity.getSupportFragmentManager().findFragmentByTag(mTag); if (preInitializedFragment != null) { // Detach the fragment, because another one is being attached ft.detach(preInitializedFragment); } } public void onTabReselected(Tab tab, FragmentTransaction ft) { // User selected the already selected tab. Usually do nothing. } }
MyFragment.java
public class MyFragment extends SherlockFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { try { Thread.sleep(2000); } catch (InterruptedException ex) { } return null; } @Override protected void onPostExecute(Void result){ getResources().getString(R.string.app_name); } }.execute(); } }
我增加了Thread.sleep
部分模拟下载数据中的代码onPostExecute
是模拟使用Fragment
...
当我在景物和肖像之间快速旋转屏幕时,我在onPostExecute
代码:
java.lang.IllegalStateException: Fragment MyFragment{410f6060} not attached to Activity
我认为这是因为同时创建了一个新的MyFragment
,并且在AsyncTask
完成之前附加到Activity
。 onPostExecute
中的代码调用一个未连接的MyFragment
。
但是我怎样才能解决这个问题?
问题在于,你正在尝试使用getResources()访问资源(在本例中是字符串)。getString(),它将尝试从活动中获取资源。参见片段类的源代码:
/** * Return <code>getActivity().getResources()</code>. */ final public Resources getResources() { if (mHost == null) { throw new IllegalStateException("Fragment " + this + " not attached to Activity"); } return mHost.getContext().getResources(); }
mHost
是保存活动的对象。
由于活动可能不附加,所以getResources()调用将引发异常。
接受的解决方案IMHO并不是要走的路,因为你只是隐藏问题。正确的方法就是从其他地方获取资源,这些资源总是被保证存在,比如应用程序上下文:
youApplicationObject.getResources().getString(...)