使用异步任务时,在循环时保存片段

时间:2013-08-09 07:05:09

标签: android android-fragments fragment screen-rotation

这个问题几乎总结了一下,我试图保存我的片段,所以当我旋转屏幕应用程序不会崩溃但我不知道在哪里或如何保存我的片段,我尝试使用片段管理器和将retainstate设置为true以及检查已保存的实例状态。

这是我的代码: EventsActivty - 托管片段

@Override
public void onCreate(Bundle savedInstanceState) {
    new AsyncLogin().execute(username, password);

    super.onCreate(savedInstanceState);

    username = getIntent().getStringExtra("username");
    password = getIntent().getStringExtra("password");
}

private List<Fragment> getFragments(){
    List<Fragment> fList = new ArrayList<Fragment>();

    EventListFragment eventListFragment = (EventListFragment)
         EventListFragment.instantiate(this, EventListFragment.class.getName());
    EventGridFragment eventGridFragment = (EventGridFragment) 
         EventGridFragment.instantiate(this, EventGridFragment.class.getName());

    fList.add(eventListFragment);
    fList.add(eventGridFragment);

    return fList;
}

此处调用getFragments,位于AsyncTask的OnPostExecute

    protected void onPostExecute(JSONObject jsonObject) {
        try {
            getEvents(jsonObject);
            setContentView(R.layout.eventlist);
            List<Fragment> fragments = getFragments();
            pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
            ViewPager pager = (ViewPager)findViewById(R.id.viewpager);
            pager.setAdapter(pageAdapter);
       }

片段1:OnCreateView

 @Override
 public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    eventObjects = ((EventsActivity)getActivity()).getEventObjects();

    setRetainInstance(true);

    View view = inflater.inflate(R.layout.eventlist ,container,false);

    final ListView listView = (ListView) view.findViewById(R.id.listView);
    listView.setAdapter(new MyCustomBaseAdapter(getActivity(), eventObjects));
    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> a, View v, int position, long id) {
            Object o = listView.getItemAtPosition(position);
            EventObject fullObject = (EventObject)o;
            System.out.println("asd");
        }
    });
    return view;
}
}

片段2:

 @Override
 public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    setRetainInstance(true);

    View view = inflater.inflate(R.layout.eventgrid ,container,false);
    GridView gridView = (GridView) view.findViewById(R.id.eventgrid);
    gridView.setAdapter(new ImageAdapter(view.getContext())); // uses the view to get the context instead of getActivity().
    return view;
}

2 个答案:

答案 0 :(得分:1)

你应该明白,保留碎片不会阻止活动被破坏。

现在看一下:

@Override
public void onCreate(Bundle savedInstanceState) {
     new AsyncLogin().execute(username, password);
     // ..... 
}

当屏幕方向发生变化时,您的活动仍会被破坏。结果,启动了新的AsyncTask。但是当旧的AsyncTask完成作业时,它会尝试将结果传递给已经销毁的旧活动。结果会导致崩溃。

解决方案是将AsyncTask放入片段本身。这样就不会在方向改变时销毁实例。

查看this article是否可以为您提供帮助。

答案 1 :(得分:1)

实际上,FragmentActivity会自动恢复onCreate()中的片段。

奇怪的是,在调用AsyncTask并从{{1}检索用户名密码之前,先调用super.onCreate() }}

即使把它放在一边,这种方法也会让你的活动每次轮换时都会产生一个新的登录任务。

更好的方法是检查Intent savedInstanceState

null

这样,它只会在第一次创建if (savedInstanceState == null) { // first launch new AsyncLogin().execute(username, password); } ... 时运行。

其次,您需要完全解除活动中的登录信息。将Activity返回到AsyncTask的任何登录结果并将其存储在那里。以及您从Application检索该信息的活动和片段 - 这样您就可以完全控制您的登录程序:您检查是否存在活动会话,如果不存在则检查是否Application已经运行,如果不是 - 你需要启动它。如果是 - 你需要等待它完成(显示进度条或其他东西)。