【问题标题】:Saving fragments on rotation when using an Async Task使用异步任务时在旋转时保存片段
【发布时间】:2013-08-09 07:05:09
【问题描述】:

这个问题总结得差不多了,我正在尝试保存我的片段,所以当我旋转屏幕时,应用程序不会崩溃,但我不确定在哪里或如何保存我的片段,我尝试使用片段管理器和将 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;
}

【问题讨论】:

  • 你可以使用服务
  • @RogerGarzonNieto 你能解释一下你的意思吗

标签: android android-fragments fragment screen-rotation


【解决方案1】:

其实FragmentActivity会自动恢复你在onCreate()中的片段。

奇怪的是,您首先调用AsyncTask,然后再调用super.onCreate() 并从Intent 检索用户名密码

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

更好的方法是检查savedInstanceState 是否有null

if (savedInstanceState == null) {
    // first launch
    new AsyncLogin().execute(username, password);
}
...

这样它只会在第一次创建Activity 时运行。

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

【讨论】:

  • 我如何让它将信息返回给应用程序
  • 在您的应用程序类中使用对this 的静态引用,单例样式:public static class MyApplication extends Application { public static MyApplication instance; public void onCreate() {MyApplication.instance = this} ... },然后通过引用它从您的异步任务的onPostExecute() 中获取应用程序,例如:MyApplication.instance.setLoggedIn(true); 和在你的Activity 你会做if (!MyApplication.instance.isLoggedIn() &amp;&amp; !MyApplication.instance.isLoginTaskRunning()) {new AsyncLogin().execute(username, password);}
【解决方案2】:

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

现在看这里:

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

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

解决方案是将 AsyncTask 放在片段本身中。这样实例就不会在方向更改时被破坏。

看看this article能不能帮到你。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 2016-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多