在Fragment上首次创建后,RecyclerView + Adapter不可见

时间:2016-11-24 03:38:55

标签: android listview android-fragments android-recyclerview adapter

我有一个片段,其中包含一个RecyclerView,这是填充改造2,在我的Listener中填充适配器并在RecyclerView上设置。

如果应用程序被杀死并重新开始,第一次打开此片段时会正确显示但如果我按后退按钮或更改片段,当我尝试进入相同时片段与适配器的RecyclerView永远不会显示。

我在gradle上使用它:

compile 'com.android.support:cardview-v7:25.0.1'
compile 'com.android.support:recyclerview-v7:25.0.1'
compile 'com.android.support:support-v4:25.0.1'

这是我的XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:orientation="vertical">

<include
    android:id="@+id/my_toolbar"
    layout="@layout/standard_toolbar" />

<com.sample.ui.CustomSwipeRefreshLayout
    android:id="@+id/ptr_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:visibility="visible">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include
            android:id="@+id/empty_rewards"
            layout="@layout/no_near_by_rewards"
            android:visibility="gone"/>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rewards_list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scrollbars="vertical"/>

    </LinearLayout>

</com.sample.ui.CustomSwipeRefreshLayoutt>
</LinearLayout>

这是我的片段类:

public class RewardsListFragment extends BaseFragment implements GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener, LocationListener {

public static volatile boolean refreshOffersListFragment = false;
public static boolean comingFromDetailFragment = false;
private static GoogleApiClient locationClient;

private int LIMIT = 7;

private View noRewards;

ArrayList<MerchantListItem> nMerchantList = new ArrayList<>();

private RewardsRVArrayAdapter mAdapter;
private RecyclerView rList;

// Bool to track whether the app is already resolving an error
private boolean resolvingError = false;
private boolean awaitingPermission = false;
private boolean appSettingsSelected = false;
private boolean locationSettingsSelected = false;
private boolean gpsOffScreenDisplayed = false;
private boolean awaitingHomeCoordinates = true;

private double homeLatitude = 0.0;
private double homeLongitude = 0.0;
private Location currentLocation = null;
private String permissionStatus;

MerchantListRequest listRequest;

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

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

    rList = (RecyclerView) view.findViewById(rewards_list);
    noRewards = view.findViewById(R.id.empty_rewards);

    rList.setHasFixedSize(true);
    LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    rList.setLayoutManager(layoutManager);
}

@Override
public void onDetach() {
    super.onDetach();
    if(mAdapter != null)
    {
        mAdapter = null;
    }

    if(rList.getAdapter() != null)
    {
        rList.setAdapter(null);
    }

    if(listRequest != null) {
        listRequest.getCall().cancel();
    }
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    homeLatitude = ChimeApplication.user.latitude;
    homeLongitude = ChimeApplication.user.longitude;

    startIndeterminateProgress();
    currentLocation = new Location("");
    currentLocation.setLatitude(homeLatitude);
    currentLocation.setLongitude(homeLongitude);
    awaitingHomeCoordinates = false;

    mAdapter = new RewardsRVArrayAdapter(new ArrayList<MerchantListItem>());
    rList.setAdapter(mAdapter);

}

@Override
public void onResume() {
    super.onResume();
    getRewards();
}

private void refreshOffers() {
        startIndeterminateProgress();
        final int first_row = 0;
        final int num_rows = LIMIT;
        listRequest = new MerchantListRequest(parentActivity, currentLocation.getLatitude(), currentLocation.getLongitude(), first_row, num_rows);
        listRequest.execute(new MerchantListRequestListener(getContext()));
}

@Override
public void onRefresh() {
    refreshOffersListFragment = true;
    refreshOffers();
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.offers_list_menu, menu);
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.refresh) {
        refreshOffersListFragment = true;
        refreshOffers();
        return true;
    }

    return false;
}

@Override
public void onPause() {
    super.onPause();

    if (locationClient != null && locationClient.isConnected()) {
        locationClient.disconnect();
    }
}

private void showList() {
    noRewards.setVisibility(View.GONE);
    rList.setVisibility(View.VISIBLE);
}

private void hideList() {
    noRewards.setVisibility(View.VISIBLE);
    rList.setVisibility(View.GONE);
}

private void setMerchantsList(ArrayList<MerchantListItem> results) {

    if (nMerchantList != null && nMerchantList.size() > 0) {
        nMerchantList.clear();
    }

    for (MerchantListItem item : results) {
        nMerchantList.add(item);
    }

    if (mAdapter == null) {
        mAdapter = new RewardsRVArrayAdapter(nMerchantList);
        rList.setAdapter(null);
        rList.setAdapter(mAdapter);
    } else {
        mAdapter.addAll(nMerchantList);
        rList.postInvalidate();
    }
}

private class MerchantListRequestListener extends BaseRetrofitRequestListener<MerchantListResult> {

    public MerchantListRequestListener(Context context) {
        super(context);
    }

    @Override
    public void onRequestFailed(int code, String errorMessage) {
        android.util.Log.e("RECYCLERVIEW", "FAIL request");
        stopIndeterminateProgress();
        dialogCheck();
        if (errorMessage != null && !errorMessage.isEmpty() && isVisible()) {
            Toast.makeText(context, errorMessage, Toast.LENGTH_LONG).show();
            hideList();
        }
    }

    @Override
    public void onRequestSuccessful(Response<MerchantListResult> response) {
        dialogCheck();
        stopIndeterminateProgress();
        if (response != null && response.body().results != null) {
            showList();

            setMerchantsList(response.body().results);


        } else {
            hideList();
        }
    }

    private void dialogCheck() {
        if (!Utils.isHighAccuracySet(parentActivity) && ContextCompat.checkSelfPermission(parentActivity, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(parentActivity, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            displayGPSOffDialog();
        }
    }
}

private void getRewards() {
    if (ContextCompat.checkSelfPermission(parentActivity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        if (!(RewardsListFragment.this).shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                awaitingPermission = true;
                (RewardsListFragment.this).requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
                                Manifest.permission.ACCESS_COARSE_LOCATION},
                        PermConst.REWARDS_LOCATION_PERMISSION_REQUESTED);
            }
        } else {
            displayPermissionDeniedDialog();
            final int first_row = 0;
            final int num_rows = LIMIT;

            listRequest = new MerchantListRequest(parentActivity, currentLocation.getLatitude(), currentLocation.getLongitude(), first_row, num_rows);
            listRequest.execute(new MerchantListRequestListener(parentActivity));
            awaitingPermission = false;
        }

    } else {
        if (locationClient != null && !locationClient.isConnected() && Utils.isHighAccuracySet(parentActivity)) {
            // Turn off no offers and gps disabled screens only if the no offers screen is not currently displayed.
            locationClient.connect();
        } else {
            if (locationClient == null && Utils.isHighAccuracySet(parentActivity)) {
                refreshOffersListFragment = true;
                locationClient = new GoogleApiClient.Builder(parentActivity.getApplicationContext())
                        .addConnectionCallbacks(this).addOnConnectionFailedListener(this).addApi(LocationServices.API).build();
                locationClient.connect();
            } else {
                final int first_row = 0;
                final int num_rows = LIMIT;

                listRequest = new MerchantListRequest(parentActivity, currentLocation.getLatitude(), currentLocation.getLongitude(), first_row, num_rows);
                listRequest.execute(new MerchantListRequestListener(parentActivity));
                if (!Utils.isHighAccuracySet(parentActivity)) {
                    gpsOffScreenDisplayed = true;
                }
            }
        }
        awaitingPermission = false;
    }

    mPullToRefreshLayout.setEnabled(true);

}

最后这是我的适配器:

public class RewardsRVArrayAdapter extends RecyclerView.Adapter<RewardsRVArrayAdapter.ViewHolder> {

private List<MerchantListItem> results;
private final int sdkVersion;
private Bitmap defaultImage;
private final DecimalFormat dollarFormatter = new DecimalFormat("$##.##");

private int lastAnimatedPosition = -1;

public RewardsRVArrayAdapter(List<MerchantListItem> results) {
    this.results = results;
    sdkVersion = Utils.getSDKVersion();
    setHasStableIds(false);
}

@Override
public RewardsRVArrayAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    // create a new view
    defaultImage = BitmapFactory.decodeResource(parent.getContext().getResources(), R.drawable.big_text);
    View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.rewards_list_item, parent, false);
    // set the view's size, margins, paddings and layout parameters
    return new ViewHolder(v);
}

@Override
public void onViewAttachedToWindow(ViewHolder holder) {
    super.onViewAttachedToWindow(holder);
}

@Override
public void onViewDetachedFromWindow(ViewHolder holder) {
    super.onViewDetachedFromWindow(holder);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    MerchantListItem offerItem = results.get(position);
    Deal deal = offerItem.deal != null ? offerItem.deal : null;

    if (offerItem.type.equalsIgnoreCase(Const.MERCHANT_MERCHANT_STRING)) {
        setMerchant(holder, offerItem, deal);
    } else if (offerItem.type.equalsIgnoreCase(Const.MERCHANT_REWARD_STRING)) {

        setCategoryReward(holder, deal);
    }

    //Set up the banner
    if (offerItem.banner != null && offerItem.banner.text != null && !offerItem.banner.text.isEmpty()) {
        holder.banner.setVisibility(View.VISIBLE);
        holder.banner.setText(offerItem.banner.text);

        //Set color of banner based on type
        if (offerItem.banner.type.equalsIgnoreCase(Banner.TYPE_FEATURED)) {
            holder.banner.setBackgroundResource(R.drawable.yellow_banner);
            holder.banner.setTextColorRes(R.color.text);
        } else if (offerItem.banner.type.equalsIgnoreCase(Banner.TYPE_PERSONALIZED)) {
            holder.banner.setBackgroundResource(R.drawable.blue_banner);
            holder.banner.setTextColorRes(android.R.color.white);
        } else if (offerItem.banner.type.equalsIgnoreCase(Banner.TYPE_LIMITED)) {
            holder.banner.setBackgroundResource(R.drawable.orange_banner);
            holder.banner.setTextColorRes(android.R.color.white);
        }

        //For some reason padding did not work in XML so I moved it here
        holder.banner.setPadding(Utils.convertDpToPixel(10, holder.banner.getContext()), Utils.convertDpToPixel(3, holder.banner.getContext()),
                Utils.convertDpToPixel(10, holder.banner.getContext()), Utils.convertDpToPixel(3, holder.banner.getContext()));
    } else {
        holder.banner.setVisibility(View.GONE);
    }
}

@Override
public int getItemCount() {
    return results != null ? results.size() : 0;
}

public MerchantListItem getItemAtPosition(int position)
{
    return results.get(position);
}

public void addAll(ArrayList<MerchantListItem> newResults)
{
    this.results.clear();
    for(MerchantListItem item : newResults)
    {
        this.results.add(item);
    }
    dataSetChanged();
}

@UiThread
protected void dataSetChanged() {
    notifyDataSetChanged();
}

private void setMerchant(final ViewHolder viewHolder, final MerchantListItem offerItem, final Deal deal) {
    loadCardImage(offerItem.image_url, viewHolder);
    viewHolder.merchant_name_txt.setText(offerItem.name);

    if (deal != null) {
        viewHolder.merchant_offer_txt.setText(deal.name);
        viewHolder.offer_amount.setText(dollarFormatter.format(deal.promotional_value));
    }
}

private void setCategoryReward(final ViewHolder viewHolder, Deal deal) {
    if(deal != null)
    {
        loadCardImage(deal.category_reward.card_image_url, viewHolder);
        viewHolder.merchant_name_txt.setText(deal.category_reward.card_title);
        viewHolder.merchant_offer_txt.setText(deal.name);
        viewHolder.offer_amount.setText(dollarFormatter.format(deal.promotional_value));
    }
}

private void loadCardImage(String url, final ViewHolder viewHolder) {
    if (url != null && !url.isEmpty()) {
        Picasso.with(viewHolder.main_layout.getContext()).load(url).memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE ).fit().networkPolicy(NetworkPolicy.NO_CACHE, NetworkPolicy.NO_STORE, NetworkPolicy.OFFLINE).into(viewHolder.main_layout);
    } else {
        setDefaultImage(viewHolder.main_layout);
    }

}

@SuppressWarnings("deprecation")
@SuppressLint("NewApi")
private void setBackgroundImage(View view, Drawable drawable) {
    //FIXME we can remove this because we don't support any below to API 16 (JELLY BEAN)
    if (sdkVersion < android.os.Build.VERSION_CODES.JELLY_BEAN) {
        view.setBackgroundDrawable(drawable);
    } else {
        view.setBackground(drawable);
    }
}

public static class ViewHolder extends RecyclerView.ViewHolder {
    // each data item is just a string in this case
    ButtonTextView banner;
    ButtonTextView merchant_name_txt;
    HeaderTextView merchant_offer_txt;
    ImageView main_layout;
    ButtonTextView offer_amount;
    public ViewHolder(View v) {
        super(v);
        banner = (ButtonTextView) v.findViewById(R.id.banner);
        merchant_name_txt = (ButtonTextView) v.findViewById(R.id.merchant_name_txt);
        merchant_offer_txt = (HeaderTextView) v.findViewById(R.id.merchant_reward_txt);
        main_layout = (ImageView) v.findViewById(R.id.image_layout);
        offer_amount = (ButtonTextView) v.findViewById(R.id.reward_amount);
    }
}

}

奇怪的是,发生在Android M和N 上,但现在正在Android L上发生,我正在阅读以前使用支持库但我找不到解决方案。

附上一个gif以检查行为是什么 Gif bug RecyclerView

2 个答案:

答案 0 :(得分:1)

由于我无法直接检查,因为您的项目有很多依赖项,我建议您记录方法的每个部分。

我认为您的getRewards()方法存在一些错误。 如果您的刷新方法工作正常,您可以使用

private boolean firstTime = true;

@Override
public void onResume() {
    super.onResume();
    if(firstTime){
        getRewards();
        firstTime = false;    
    }
    else{
        onRefresh();
    }
}

代替

答案 1 :(得分:0)

在RewardsListFragment

中的onCreateView中添加以下代码
mAdapter = new RewardsRVArrayAdapter(new ArrayList<MerchantListItem>());
rList.setAdapter(mAdapter);