回滚后,ViewPager中的片段在onResume上为空白

时间:2017-08-03 15:20:01

标签: java android android-fragments

我在ViewPager中使用MainActivityFragmentPagerAdapter有四个片段。在片段中,数据显示在ListView上,并带有自定义适配器NewsAdapter。此数据从网络加载并通过Loader返回到片段。一切都适用于应用程序的初始创建,数据加载到视图上没有错误。我遇到的问题是当我滚动ViewPager跨越两个标签时onDestroyView在片段中调用了两个标签,当我返回到该片段时,除ProgressBar之外没有任何东西被夸大,调用View.GONE时设置为onLoadFinished。这首先按预期工作。

  • 我注意到即使在我返回片段时调用onLoadFinishedmProgressBar.setVisibility.(View.GONE)也没有被执行。
  • 我已检查mAdapteronCreateView不为空,并且设置为空onDestroyView,因此我认为Loader正在更新mAdapter时我回到了每个片段
  • 当我旋转设备onDestroy并在onResume中调用MainActivity时,屏幕上没有任何内容被绘制,直到我再次旋转(返回垂直),然后片段状态如预期直到滚动。
  • 我尝试将FragmentPagerAdapter更改为FragmentStatePagerAdapter,但没有任何更改。
  • 我已在mAdapter中清除了mRootViewonDestroyView,以便在onResume片段
  • 中传递双重检查数据

以下是我的一个片段(除了名称和Loader ID之外,它们都是相同的)

package com.example.android.greennewswire;

import android.app.LoaderManager; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ListView; import android.widget.ProgressBar;

import java.util.ArrayList;


public class NewsFragmentSky extends Fragment implements LoaderManager.LoaderCallbacks<ArrayList<News>>{

    public NewsFragmentSky() {
        // Required empty public constructor
    }

    //String object holding the network request URL to be passed into the Loader
    private static final String NEWS_REQUEST_URL = "https://www.googleapis.com/books/v1/volumes?q=android";

    private static final String LOG_TAG = "NewsFragmentBBC";

    private NewsAdapter mAdapter;
    private View mRootView;
    private ProgressBar mProgressBar;


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mRootView = inflater.inflate(R.layout.list, container, false);

        //Create a LoaderManager and initialise the Loader
        LoaderManager loaderManager = getActivity().getLoaderManager();
        loaderManager.initLoader(4, null, this);

        mProgressBar = (ProgressBar) mRootView.findViewById(R.id.progress_bar);
        //TODO fix context problem!
        mAdapter = new NewsAdapter(getActivity(), new ArrayList<News>());
        ListView listView = (ListView) mRootView.findViewById(R.id.list);
        listView.setAdapter(mAdapter);

        boolean rootViewEmpty = (mRootView == null);
        Log.i(LOG_TAG, "rootView null? " + rootViewEmpty);
        Log.i(LOG_TAG, "onCreateView called");
        return mRootView;
    }


    @Override
    public void onDestroyView() {
        mAdapter.clear();
        mRootView = null;
        boolean rootViewEmpty = (mRootView == null);
        Log.i(LOG_TAG, "rootView null? " + rootViewEmpty);
        Log.i(LOG_TAG, "onDestroyView called.");
        super.onDestroyView();
    }
    @Override
    public void onPause() {
        Log.i(LOG_TAG, "onPause called.");
        super.onPause();
    }
    @Override
    public void onStop() {
        Log.i(LOG_TAG, "onStop called.");
        super.onStop();
    }

    @Override
    public void onResume() {
        Log.i(LOG_TAG, "onResume called.");
        super.onResume();
    }

    @Override
    public android.content.Loader<ArrayList<News>> onCreateLoader(int i, Bundle bundle) {
        Log.i(LOG_TAG, "onCreateLoader called.");
        return new NewsLoader(getContext(), NEWS_REQUEST_URL);
    }

    @Override
    public void onLoadFinished(android.content.Loader<ArrayList<News>> loader, ArrayList<News> newses) {
        mAdapter.addAll(newses);
        mProgressBar.setVisibility(View.GONE);
        boolean adapterState = mAdapter.isEmpty();
        Log.i(LOG_TAG, "onLoadFinished mAdapter null? " + adapterState);
    }

    @Override
    public void onLoaderReset(android.content.Loader<ArrayList<News>> loader) {
        Log.i(LOG_TAG, "onLoaderReset called.");
        mAdapter.clear();
    } }

FragmentAdapter

package com.example.android.greennewswire;

import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.util.Log;

public class FragmentAdapter extends FragmentPagerAdapter {

private static final String LOG_TAG = FragmentAdapter.class.getSimpleName();
private Context mContext;

public FragmentAdapter(Context context, FragmentManager fm) {
    super(fm);
    mContext = context;
}

@Override
public Fragment getItem(int position) {
    if (position == 0) {
        Log.i(LOG_TAG, "FragmentAdapter position: " + position);
        return new NewsFragmentBBC();
    } else if (position == 1) {
        Log.i(LOG_TAG, "FragmentAdapter position: " + position);
        return new NewsFragmentReuters();
    } else if (position == 2) {
        Log.i(LOG_TAG, "FragmentAdapter position: " + position);
        return new NewsFragmentRT();
    } else {
        Log.i(LOG_TAG, "FragmentAdapter position: " + position);
        return new NewsFragmentSky();
    }
}

@Override
public int getCount() {
    return 4;
}

@Override
public CharSequence getPageTitle(int position) {
    if (position == 0) {
        return mContext.getString(R.string.category_bbc);
    } else if (position == 1) {
        return mContext.getString(R.string.category_reuters);
    } else if (position == 2) {
        return mContext.getString(R.string.category_rt);
    } else {
        return mContext.getString(R.string.category_sky);
    }
}
}

修改:我为片段的LoaderManageronDestroy创建了一个局部变量,名为destroyLoader(i)。这似乎有效,当我滚动选项卡中的片段并返回时,片段视图是使用数据创建的。我只是添加了这个,因为我不确定这是否是最佳做法?我希望这会创建一个新的Loader并在每次创建片段时从网络获取数据,这实际上会使Loader无法解决问题。我的假设是正确的吗?

Edit2:我现在在每个片段的mLoaderManager.initLoader(id, null, this)方法中调用onResume。当我滚动选项卡时,检查Android Studio监视网络流量图只能从网络中获取一次数据。我仍然有一个问题,虽然手机旋转,视图不是在第一次旋转(横向)创建,但旋转回到肖像应用程序行为是预期的。我接下来会查看我的MainActivity生命周期。

0 个答案:

没有答案