实现 Fragment 实例化会产生相反的效果

Implementing Fragment instantiation causes opposite effect

I have implemented my fragment to the Android's best practice of using newInstance with parameters. 可以,但有一个舱口。

带参数的 newInstance 修复的问题是 Android 将在屏幕旋转时调用默认的无参数构造函数。这意味着您将丢失轮换数据。 newInstance 将允许您 setArguments 将保留轮换。

使用 overloaded constructor 意味着您的数据将在第一次正确显示,直到您旋转设备。 newInstance 将使您的片段在第一次和轮换时都能正常工作。

问题

然而,我好像适得其反。我的代码在旋转时工作正常,但在第一次尝试时工作不正常。如果我使用带参数的构造函数,也会出现同样的效果。

应用程序加载时,它会在 Tablayout 中显示我的选项卡 (3),但我的 RecyclerView 中的 none 将包含项目。

以下是我如何以最快的速度将数据加载到 RecyclerView 中。全部在应用程序加载中,并且全部从新开始:

  1. 旋转设备。所有 3 个选项卡都将加载它们的数据。现在是当前选项卡,选择其他选项卡(滑动到它们)。
  2. 从第一个选项卡,单击选项卡 3,然后返回选项卡 1。将加载选项卡 1 的数据。标签 2 不会加载。选项卡 3 将在选择时加载。要加载 Tab 2 数据,我需要旋转设备

代码

片段

public class MovieListFragment extends Fragment implements OnItemClickListener {

    MovieListAdapter adapter;
    WebAPI webAPI;     // Advanced Enum

    private static final String API_STRING = "api";

    public MovieListFragment() {}

    public static MovieListFragment newInstance(WebAPI API) {

        MovieListFragment fragment = new MovieListFragment();

        Bundle args = new Bundle();
        args.putSerializable(API_STRING, API);
        fragment.setArguments(args);

//        if (API != null) fragment.webAPI = API;

        return fragment;

    }

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

        View rootView = inflater.inflate(R.layout.fragment_movies_list, container, false);

        webAPI = (WebAPI) getArguments().getSerializable(API_STRING);

        GetMoviesAsync getMovies = new GetMoviesAsync();
        getMovies.execute();

        adapter = new MovieListAdapter(getActivity(), webAPI, this);

        RecyclerView movieListView;

        movieListView = (RecyclerView) rootView.findViewById(R.id.movie_list);
        movieListView.setAdapter(adapter);
        movieListView.setLayoutManager(
                new GridLayoutManager(  // Changes number of columns based on form-factor and orientation
                        getActivity(),
                        getResources().getInteger(R.integer.columns)));


        return rootView;

    }

    @Override
    public void onClick(View v, int position) {

        startActivity(new Intent(this.getActivity(), SecondaryActivity.class)); // TODO pass data to second activity

    }

    // ASYNC_TASK
    public class GetMoviesAsync extends AsyncTask<Void, Void, Void> {

        // CALLBACK
        private final Handler.Callback getMoviesFromJSON = new Handler.Callback() {

            @Override
            public boolean handleMessage(Message msg) {

                        // Take the JSON (msg) and convert it to a Java object (Movie)
                        Movie movie = new Movie(title, uri);
                        webAPI.addMovie(movie);

                    }

                } catch (JSONException e) { return false; }

                return true;

            }

        };

        @Override
        protected Void doInBackground(Void... params) {

            try {

                // This will get the JSON from the webservice, and will use the CallBack to assign the List of movies.
                new WebService(webAPI.getUri()).acquireDataWithCallback(getMoviesFromJSON);

            } catch (JSONException e) { e.printStackTrace(); }

            return null;
        }

    }

}

基础活动

public abstract class BaseSearchTabbedActivity extends AppCompatActivity
        implements SearchView.OnQueryTextListener {

    EnumSet<WebAPI> tabs;
    ...

    public void setTabs(EnumSet<WebAPI> tabs) { this.tabs = tabs; }

    void initializeToolbar() {   // Called in Activity's OnCreate

        // Setup the toolbar
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        // Initialize all components. Tabs, Pager, and Adapter
        tabLayout = (TabLayout) findViewById(R.id.tabs);
        viewPager = (ViewPager) findViewById(R.id.pager);
        adapter = new ViewPagerFragmentAdapter(getSupportFragmentManager());

        // Add the tabs
        collectTabValues(); // Set tabs from Activity
        addFragments(tabs);

        // Bind the adapter to the tabs
        viewPager.setAdapter(adapter);
        tabLayout.setupWithViewPager(viewPager);

    }

    private void addFragments(EnumSet<WebAPI> tabs) {

        for (WebAPI tab : tabs) {

            adapter.addFragment(MovieListFragment.newInstance(tab), tab);

        }

    }

只要异步任务完成它的工作,您就需要更新适配器并通知它的项目有变化。

更新适配器视图需要在主线程中,所以请在您的任务中添加以下方法:

@Override
protected void onPostExecute(Void nothing) {
    adapter.notifyDataSetChanged();
}