我有一个片段,其中包含一个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
答案 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);