Drawer + Tab + ViewPager和每个片段从服务器加载数据

时间:2016-10-05 10:05:57

标签: android android-fragments android-viewpager android-tablayout

抽屉中的某些菜单会打开Tab + ViewPager内容。每个页面(片段)都是从服务器请求其数据的列表。

每次单击该菜单时,我都希望内容会立即显示标签,即使仍然请求数据而不是空屏幕。我尝试在TabFragment中添加进度条,以便在准备ViewPager和寻呼机数据时内容将显示加载。但是,内容仍然显示没有加载指示器的空屏幕。我发现问题是因为从每个寻呼机调用从服务器请求数据的方法。

我应该将请求数据的方法移到TabFragment吗?

我的TabFragment类看起来像:

public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    .....

    content = view.findViewById(R.id.content);
    content.setVisibility(View.GONE);
    tabLayout = (TabLayout) view.findViewById(R.id.tabs);
    viewPager = (ViewPager) view.findViewById(R.id.pager);

    progressBar = (ProgressBar) view.findViewById(R.id.progressBar1);

    farmerViewPagerAdapter = new FarmerViewPagerAdapter(getChildFragmentManager(), titles);
    viewPager.setOffscreenPageLimit(2);
    viewPager.setAdapter(farmerViewPagerAdapter);
        tabLayout.post(()->{
            tabLayout.setupWithViewPager(viewPager);
            for (int i = 0; i < titles.length; ++i){
                tabLayout.getTabAt(i).setIcon(icons[i]);
            }
        });
}

这里是每个页面的片段(每个页面请求不同的数据):

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    this.view = view;

    emptyView = view.findViewById(R.id.emptyView);
    emptyText = (TextView) view.findViewById(R.id.emptyTextView);

    recyclerView = (RecyclerView) view.findViewById(R.id.list);

    recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
    recyclerView.setItemAnimator(new DefaultItemAnimator());

    adapter = new FarmerAdapter(data, getContext());

    recyclerView.setAdapter(adapter);
    recyclerView.addItemDecoration(
            new HorizontalDividerItemDecoration.Builder(getContext())
                    .showLastDivider()
                    .marginResId(R.dimen.divider_margin_left, R.dimen.divider_margin_right)
                    .build());

    swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeRefreshLayout);
    swipeRefreshLayout.setOnRefreshListener(() -> {

                if (!Util.isNetworkAvailable(getContext())) {
                    if (swipeRefreshLayout.isRefreshing()) swipeRefreshLayout.setRefreshing(false);
                } else {
                    currentPage = 1;
                    loadData(); //method to request data from server
                }
            }
    );


    if (user != null) {
        getDataFromLocal();
        addToAdapter();
        loadData();
    }

}

(Ed)loadData方法:

Observable<Response<List<Data>>> dataApi = request.getServerData(currentPage,
            NUMBER_DATA_PER_PAGE, 
            token);
    dataApi.subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(responseData -> {
                if (swipeRefreshLayout.isRefreshing()) swipeRefreshLayout.setRefreshing(false);
                if (responseData.isSuccessful() && responseData.code() == 200) {

                    currentPage++;

                    adapter.add(responseData.body());
                    if (adapter.getItemCount() < 1) {
                        emptyText.setText("Empty");
                        emptyView.setVisibility(View.VISIBLE);
                    }

                } else {
                    try {
                        JSONObject json = new JSONObject(responseFarmer.errorBody().string());
                        Toast.makeText(getContext(), json.getString("message"), Toast.LENGTH_LONG).show();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }, error -> {
                if (swipeRefreshLayout != null && swipeRefreshLayout.isRefreshing())
                    swipeRefreshLayout.setRefreshing(false);
                if (error != null && error.getLocalizedMessage() != null)
                    Toast.makeText(getContext(), error.getLocalizedMessage(), Toast.LENGTH_LONG).show();
            });

此方法从寻呼机片段调用。

1 个答案:

答案 0 :(得分:0)

你的AsyncTask有一个空的doInBackground()体。这基本上使它同步。假设你有这个AsyncTask:

private class SetAdapterTask extends AsyncTask<Void,Void,Void> {

    protected Void doInBackground(Void... params) {
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            doPostExecute();
        }

        @Override
        protected void onPreExecute() {
            doPreExecute();
        }
    }

你可以在你的代码中这样称呼它:

public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    .....
    new SetAdapterTask().execute();
}

但由于你的AsyncTask在后台没有做任何事情,postExecute会在preExecute之后立即触发,使整个事情等同于:

public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    .....
    doPreExecute();
    doPostExecute();
}

换句话说,您可以在preExecute中使ProgressBar可见,并在postExecute中使其消失后立即显示。

正确的方法是将ProgressBar可见性设置移动到用于加载数据的AsyncTask,该数据位于我假设的loadData()中的某个位置。至于数据加载本身,如果没有看到加载数据的实际方法,很难说出了什么问题。