2012-12-21 55 views
3

我正在爲Android創建文件管理器應用程序,下面的兩個類是執行此操作的大部分邏輯。我在做的是,在啓動ContentList時,它將ContentListFragment添加到ContestList xml中的容器佈局。通過添加ContentListFragment,我得到當前路徑,然後調用setFileDir(String S),它基本上獲取傳入路徑中的文件,獲取該位置的文件列表,初始化該數組,然後初始化適配器。然後我設置適配器,設置Action Bar UI和上下文Action Bar。現在,每次按下ContentListFragment上的項目時,都會使用所選項目的路徑創建另一個ContentListFragment。之前的片段被添加到後端堆棧。現在這一切都很好,而且方向發生時,問題就來了。在定位更改中保存片段狀態

ContentListFragment的onCreate中的setRetainInstance(true)是當應用程序更改方向時保持整個應用程序無法關閉的唯一方法。但是,這樣做會導致應用程序在稍後返回時強制關閉(這是我遇到的主要問題,並且無法理解爲什麼)。

我嘗試用方向更改(此代碼不在此之下)上重新創建活動時用新方法替換當前的ContentListFragment,但應用程序強制也在setFileDir()處關閉了NullPointerException,因此其他所有內容分崩離析。

如何保存片段狀態,以便在方向更改時保持所有狀態與更改方向前保持一致,並且在稍後再次返回時會強制關閉。

爲了以防萬一,我的應用程序只是一個具有遞歸ContentListFragments的Activity。

public class ContentList extends DrawerActivity implements ContentListFragment.listFragmentListener{ 

    // instance variables 
    private FragmentManager fm; 
    private FragmentTransaction ft; 
    private String currentPath; 

    // Initializes variables. 
    // If Activity is started for the first time, a path to the storage is 
    // received. 
    // Else, if it's an orientation change, the path is just retained. 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.content_list); 

     if (savedInstanceState == null) { 
      fm = getSupportFragmentManager(); 
      ft = fm.beginTransaction(); 
      File file = Environment.getExternalStorageDirectory(); 
      currentPath = file.getPath(); 
      ft.add(R.id.content_container_fragment_listview, new ContentListFragment()); 
      ft.commit(); 
     } else { 
      fm = getSupportFragmentManager(); 
      currentPath = savedInstanceState.getString("PATH"); 
     } 
    } 

    // Grabs the currentPath in case of orientation changes. 
    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     super.onSaveInstanceState(outState); 
     outState.putString("PATH", currentPath); 
    } 

dfsas

public class ContentListFragment extends SherlockListFragment { 

    // instance variables 
    private ArrayList<Item> items; 
    private ArrayList<Item> copy_move_queue_items; 
    private ItemAdapter adapter; 
    private listFragmentListener lfListener; 
    private String currentPath; 
    private MenuItem menuItemRename; 

    // instantiates variables using setFileDir() and the path from the container Activity. 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setRetainInstance(true); 
     currentPath = ((ContentList) getActivity()).getCurrentPath(); 
     setFileDir(currentPath); 

    } 

    // Gets a reference to Activity interface 
    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     try { 
      lfListener = (listFragmentListener) activity; 
     } catch (ClassCastException e) { 
      throw new ClassCastException(activity.toString() 
        + "must implement listFragmentListener"); 
     } 
    } 

    // Sets the UI of the listView and the ActionBar 
    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 

     View v = inflater.inflate(R.layout.content_list_fragment, container, false); 

     File file = Environment.getExternalStorageDirectory(); 
     String rootPath = file.getPath(); 

     // Sets Action Bar title to current directory, and creates an Up 
     // affordance if the root path doesn't equal the current Path 
     getSherlockActivity().getSupportActionBar().setTitle(null); 
     getSherlockActivity().getSupportActionBar().setLogo(R.drawable.ab_icon); 

     if (currentPath.equals(rootPath)) { 
      getSherlockActivity().getSupportActionBar() 
        .setDisplayHomeAsUpEnabled(false); 
      getSherlockActivity().getSupportActionBar() 
        .setHomeButtonEnabled(false); 
     } else { 
      getSherlockActivity().getSupportActionBar() 
        .setDisplayHomeAsUpEnabled(true); 



      // getSherlockActivity().getSupportActionBar().setTitle("/" + 
      // (currentPath.substring(currentPath.lastIndexOf("/") +1))); 
     } 

     return v; 

    } 

    // Sets the long click Contextual Action Mode to the ListView 
    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     super.onActivityCreated(savedInstanceState); 
     setActionMode(); 
     setListAdapter(adapter); 
    } 
    // Gets the list of files at the path and adds them to the Item ArrayList, 
// initializing the adapter as well 
public void setFileDir(String path) { 
    File file = new File(path); 
    File[] files = file.listFiles(); 
    Arrays.sort(files, new fileComparator()); 
    items = new ArrayList<Item>(); 
    for (File f : files) { 
     items.add(new Item(f)); 
    } 
    adapter = new ItemAdapter(getActivity(), R.layout.content_list_item, items); 
} 

回答

12

時使用此節省取向片段的狀態。

onCreate(Bundle save) 
{ 
    super.onCreate(save); 
    setRetainInstance(true); 
} 
+0

我沒有注意到Fragment.setRetainInstance()存在......這個API讓生活變得更容易! –

+3

setRetainInstance(true);如果在後臺添加片段,則不起作用。 – ovluca

0

剛剛發佈這個,因爲這是在面對工作和採訪:) API 13之前我們使用onRetainNonConfigurationInstance一個主要問題()它被廢棄了(此方法是涉及到活動這是目前移動在片段中),現在我們有一個新方法,即setRetainInstance()(片段類的方法部分),即使在活動創建後,這也會保存片段的狀態。

4

這個工作對我來說

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

和清單文件,你的活動標籤內

android:configChanges="orientation|screenSize"

+0

謝謝,它的工作! –