【问题标题】:I can't save instance of fragment to not restart after screen rotation我无法保存片段实例以在屏幕旋转后不重新启动
【发布时间】:2015-07-20 10:56:30
【问题描述】:

我的片段代码如下所示:

public class AllIssuesFragment extends Fragment {

@Bind(R.id.list_all_issues) ListView mListAllIssues;
IssuesGetter ai;
ArrayAdapter<IssuesResponse.Issue> adapter;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_all_issues, container, false);
    return view;
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ButterKnife.bind(this, view);
    setRetainInstance(true);

    SharedPreferences user_data = this.getActivity().getSharedPreferences("user_data", Context.MODE_PRIVATE);
    UserManager.getInstance().setUsername(user_data.getString("username", null));
    UserManager.getInstance().setPassword(user_data.getString("password", null));

    if(UserManager.getInstance().getUsername() == null || UserManager.getInstance().getPassword() == null) {
        Intent intent = new Intent(getActivity(), ChangeUserActivity.class);
        startActivity(intent);
    }
    else {
        adapter  = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1);
        if(savedInstanceState == null) {
            getIssues(Constants.URI + Constants.ISSUES + Constants.OFFSET + 0);
        }
        mListAllIssues.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView absListView, int i) {

            }

            @Override
            public void onScroll(AbsListView absListView, int firstVisible, int visibleCount, int totalCount) {
                boolean loadMore = firstVisible + visibleCount >= totalCount;

                if (loadMore && ai.getStatus() == AsyncTask.Status.FINISHED) {
                    getIssues(Constants.URI + Constants.ISSUES + Constants.OFFSET + totalCount);
                    mListAllIssues.setSelection(totalCount);
                }
            }
        });
    }
}

private void getIssues(String url) {
    ai = new IssuesGetter(new AsyncCallback<IssuesResponse>() {
        @Override
        public void onSuccess(IssuesResponse response) {
            int index = mListAllIssues.getFirstVisiblePosition();
            View v = mListAllIssues.getChildAt(0);
            int top = (v == null)? 0 : v.getTop();

            adapter.addAll(response.getIssues());
            adapter.notifyDataSetChanged();
            mListAllIssues.setAdapter(adapter);
            mListAllIssues.setSelectionFromTop(index, top);
        }

        @Override
        public void onError() {
            Intent intent = new Intent(getActivity(), ChangeUserActivity.class);
            startActivity(intent);
        }
    });
    ai.execute(url);
}
}

MainActivity.java

public class MainActivity extends AppCompatActivity {


@Bind(R.id.viewpager) ViewPager viewPager;
@Bind(R.id.tabs) PagerSlidingTabStrip tabStrip;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);
    viewPager.setAdapter(new MainActivityPagerAdapter(getSupportFragmentManager()));
    tabStrip.setViewPager(viewPager);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_change_user) {
        Intent intent = new Intent(this, ChangeUserActivity.class);
        this.startActivity(intent);
        return true;
    }

    return super.onOptionsItemSelected(item);
}
}

我尝试使用 setRetainInstance(true) 并检查 savedInstanceState 是否等于 null,但这并没有解决我的问题.我被卡住了:(

我的 Asynctask 使用回调返回结果。

【问题讨论】:

  • 你能显示使用这个片段的活动的代码吗?
  • private ArrayList&lt;IssuesResponse.Issue&gt; cache; then ... in getIssues ... if cache != null 然后从中设置适配器 ... 如果为 null 则执行 asynctask 并从响应中设置 cache。 getIssues() 并设置适配器...关键是片段不保留与 UI 组件一起使用... edit 似乎您正在使用分页...那么它不会那么容易...
  • @Nolane,我添加了它。
  • @Selvin,是的,我正在使用分页。而且我是新手,所以很难实现这个功能。
  • @VitalyRomaniv 我想看看Activity类的代码。

标签: android android-fragments rotation screen-orientation savestate


【解决方案1】:

我在这里看到了问题:

public void onCreate() {
    //..
    viewPager.setAdapter(new MainActivityPagerAdapter(getSupportFragmentManager()));
    tabStrip.setViewPager(viewPager);
}

每次重新创建活动时都会调用此方法。它所做的是创建新的适配器来创建全新的片段。这是一个问题。因为您的活动不控制片段的创建。这是保留片段所必需的。

我建议你在 onSaveInstanceState() 回调中保存片段的状态,并在 onCreateView() 中恢复它。请注意,您不需要只保存片段类的变量的 UI 元素的状态。如果 UI 元素具有唯一 ID,则它们会自动保存其状态。

编辑:

我的建议:

public class AllIssuesFragment extends Fragment {
    private List<String> issues;
    // ..

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // ..
        if (null != savedInstanceState) {
            issues = savedInstanceState.getStringArray("issues");
        } else {
            issues = new List<>();
        }
        adapter  = new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_1, issues);
        // ..
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putStringArray("issues", issues);
    }

    private void getIssues(String url) {
        // ..
        ai = new IssuesGetter(new AsyncCallback<IssuesResponse>() {
            @Override
            public void onSuccess(IssuesResponse response) {
                // ..
                //adapter.addAll(response.getIssues());
                issues.addAll(response.getIssues());
                adapter.notifyDataSetChanged();
                // ..
            }
        };
        // ..
    }
}

【讨论】:

  • 你能详细告诉我该怎么做吗?
  • @VitalyRomaniv,如果不深入代码,很难谈论细节。
  • 好的。我应该覆盖 AllIssuesFragment 中的 onSaveInstanceState 吗?但是我怎样才能在那里保存片段的状态?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多