【发布时间】:2018-01-20 17:57:17
【问题描述】:
几天来,我一直在尝试在我的 android 应用上实现一些东西,但没有成功。
我有一个显示产品的回收站视图。产品包装在 cardView 中,gridLayoutManager 为我处理布局。 cardView 包含一个 textView(产品名称)和一个 simpleDraweeView(产品图像)。
我成功地添加了一个 SwipeRefreshLayout,当用户向下滑动时,产品会刷新并添加新内容(如果存在)。 textView 在刷新时更新得很好。但是,simpleDraweeView 在我向下滚动并再次向上滚动之前不会显示新产品的图像。
我研究了这个问题并遇到了这个问题:https://github.com/facebook/fresco/issues/687。但是该帖子并未完全说明如何正确设置。
下面是我的代码sn-ps:
刷新片段(MainActivityFragment 类)
//set refresh more listener for the RecyclerView adapter
mainActivityAdapter.setOnRefreshMoreListener(new OnRefreshMoreListener() {
@Override
public void onRefreshMore() {
swipeRefreshLayout.setRefreshing(true);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
productsArrayList.clear(); //I'm removing previous data
mainActivityAdapter.notifyDataSetChanged();
fetchOnLoad(); //Function that adds new elements to the productsArrayList
mainActivityAdapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
}
}, 1000);
}
});
onBindView 片段(MainActivityAdapter)
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
if (holder instanceof ProductViewHolder) {
final Product product = mProducts.get(position);
Uri uri = Uri.parse(product.getProductImage());
final ProductViewHolder productViewHolder = (ProductViewHolder) holder;
productViewHolder.productName.setText(product.getProductName());
productViewHolder.cardImage.setImageURI(uri);
}
}
就像我在上面发布的链接中一样,我也认为 Fresco 没有显示新加载的图像,因为 onBindViewHolder 没有被再次调用。在我滚动出视图并再次进入视图后,图像总是出现。我可以像他解决的那样在 ViewHolder 中设置数据吗?如果是这样,怎么做? 任何帮助将不胜感激。 谢谢
编辑: 根据要求,这里是 fetchOnLoad 的代码
public void fetchOnLoad() {
// showing refresh animation before making http call
swipeRefreshLayout.setRefreshing(true);
// appending offset to url
String url = "https://www.example.com/spilljson.php";
// Volley's json array request object
JsonArrayRequest req = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
if (response.length() > 0) {
// looping through json and adding to product list
for (int i = 0; i < response.length(); i++) {
try {
JSONObject productObj = response.getJSONObject(i);
String image = productObj.getString("productImage");
String name = productObj.getString("productName");
Product product = new Product();
product.setProductName(name); //This works fine. New product names always shown
product.setProductImage(image); //This is where I get the issue. New product images are not shown.
products.add(product); //Add the individual product to the products arrayList
} catch (JSONException e) {
Log.e(TAG, "JSON Parsing error: " + e.getMessage());
}
}
mainActivityAdapter.notifyDataSetChanged();
}
// stopping swipe refresh
swipeRefreshLayout.setRefreshing(false);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Server Error: " + error.getMessage());
Toast.makeText(mActivity, "We can't access our servers :-(", Toast.LENGTH_LONG).show();
// stopping swipe refresh
swipeRefreshLayout.setRefreshing(false);
}
});
// Adding request to request queue
FrescoApplication.getInstance().addToRequestQueue(req);
}
问题截图 这是截图的链接:https://imgur.com/QQjEviS
完整的 MainActivityAdapter
public class MainActivityAdapter
extends RecyclerView.Adapter<MainActivityAdapter.ViewHolder> {
private RecyclerView mRecyclerView;
private final int VIEW_TYPE_ITEM = 0;
private final int VIEW_TYPE_LOADING = 1;
private OnLoadMoreListener onLoadMoreListener;
private OnRefreshMoreListener onRefreshMoreListener;
private boolean isLoading;
private List<Product> mProducts;
private SwipeRefreshLayout mSwipeRefresh;
private int visibleThreshold = 5;
private int lastVisibleItem, totalItemCount;
public static final String STRING_IMAGE_URI = "ImageUri";
public static final String STRING_IMAGE_POSITION = "ImagePosition";
private static MainActivity mActivity;
public MainActivityAdapter(RecyclerView recyclerView, SwipeRefreshLayout refreshLayout, List<Profile> products, MainActivity myContext) {
mRecyclerView = recyclerView;
mProducts = products;
mActivity = myContext;
mSwipeRefresh = refreshLayout;
final GridLayoutManager gridLayoutManager = (GridLayoutManager) recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = gridLayoutManager.getItemCount();
lastVisibleItem = gridLayoutManager.findLastVisibleItemPosition();
if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
if (onLoadMoreListener != null) {
onLoadMoreListener.onLoadMore();
}
isLoading = true;
}
}
});
mSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
if (onRefreshMoreListener != null) {
onRefreshMoreListener.onRefreshMore();
}
}
});
}
public void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) {
this.onLoadMoreListener = mOnLoadMoreListener;
}
public void setOnRefreshMoreListener(OnRefreshMoreListener mOnRefreshMoreListener) {
this.onRefreshMoreListener = mOnRefreshMoreListener;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public final View mView;
public final SimpleDraweeView mImageView;
public final RelativeLayout mLayoutItem;
public ViewHolder(View view) {
super(view);
mView = view;
mImageView = (SimpleDraweeView) view.findViewById(R.id.user_image_listing);
mLayoutItem = (RelativeLayout) view.findViewById(R.id.layout_item);
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_ITEM) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.main_layout_profile, parent, false);
return new ProductViewHolder(view);
} else if (viewType == VIEW_TYPE_LOADING) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_loading, null, false);
return new LoadingViewHolder(view);
}
return null;
}
@Override
public void onViewRecycled(ViewHolder holder) {
if (holder instanceof ProductViewHolder) {
ProductViewHolder productViewHolder = (ProductViewHolder) holder;
if (productViewHolder.mImageView.getController() != null) {
productViewHolder.mImageView.getController().onDetach();
}
if (productViewHolder.mImageView.getController() != null) {
productViewHolder.mImageView.getTopLevelDrawable().setCallback(null);
}
}
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
if (holder instanceof ProductViewHolder) {
final Product product = mProducts.get(position);
Uri uri = Uri.parse(product.getProductImage());
final ProductViewHolder productViewHolder = (ProductViewHolder) holder;
productViewHolder.productName.setText(product.getProductName());
productViewHolder.cardImage.setImageURI(uri);
}
}
@Override
public int getItemCount() {
return mProducts == null ? 0 : mProducts.size();
}
public void setLoaded() {
isLoading = false;
}
@Override
public int getItemViewType(int position) {
return mProducts.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
}
private class LoadingViewHolder extends ViewHolder {
public ProgressBar progressBar;
public LoadingViewHolder(View view) {
super(view);
progressBar = (ProgressBar) view.findViewById(R.id.progressBar1);
}
}
private class ProductViewHolder extends ViewHolder {
public TextView productName;
public SimpleDraweeView cardImage;
public ProductViewHolder(View view) {
super(view);
productName = (TextView) view.findViewById(R.id.txt_product_name);
cardImage = (SimpleDraweeView) view.findViewById(R.id.product_image);
}
}
}
完整的 MainActivityFragment
public class MainActivityFragment extends Fragment {
public static final String STRING_IMAGE_URI = "ImageUri";
public static int SPAN_SIZE = 2;
public static final String STRING_IMAGE_POSITION = "ImagePosition";
public static final String STRING_PRODUCT_NAME = "Name";
private static MainActivity mActivity;
private List<Product> productsArrayList;
private MainActivityAdapter mainActivityAdapter;
private SwipeRefreshLayout swipeRefreshLayout;
private Connectivity connectivity; //Simple class I created to check when internet connection is available or not. Works fine.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = (MainActivity) getActivity();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
swipeRefreshLayout = (SwipeRefreshLayout) inflater.inflate(R.layout.main_layout_recyclerview, container, false);
setupRecyclerView(swipeRefreshLayout);
return swipeRefreshLayout;
}
private void setupRecyclerView(final SwipeRefreshLayout swipeRefreshLayout) {
RecyclerView recyclerView = (RecyclerView) swipeRefreshLayout.findViewById(R.id.recyclerview);
productsArrayList = new ArrayList<>();
connectivity = new Connectivity(mActivity);
//The same data is being displayed across the 3 viewpagers I have for now...
if (MainActivityFragment.this.getArguments().getInt("type") == 1) {
SPAN_SIZE = 2;
} else if (MainActivityFragment.this.getArguments().getInt("type") == 2) {
SPAN_SIZE = 2;
} else if (MainActivityFragment.this.getArguments().getInt("type") == 3) {
SPAN_SIZE = 1;
}
//If internet connection is found... fetch content
if(connectivity.isInternetAvailable()){
//This fetches the data from the internet and adds it to the products ArrayList declared above.
fetchOnLoad();
} else{
Toast.makeText(mActivity, "No Internet", Toast.LENGTH_SHORT).show();
}
//If products were added to the ArrayList, proceed
if (productsArrayList != null) {
GridLayoutManager layoutManager = new GridLayoutManager(mActivity,SPAN_SIZE,GridLayoutManager.VERTICAL,false);
recyclerView.setLayoutManager(layoutManager);
mainActivityAdapter = new MainActivityAdapter(recyclerView, swipeRefreshLayout, productsArrayList, mActivity);
recyclerView.setAdapter(mainActivityAdapter);
swipeRefreshLayout.setColorSchemeColors(getResources().getColor(R.color.colorAccent));
//Load more listener for the RecyclerView adapter - working just fine. However, I fear it
//will have the same problem when I start introducing new products. NB: The JSON that is on my server has static information.
//This limits the number of visible products to 40 for now as I am reusing data from the
//products ArrayList.
mainActivityAdapter.setOnLoadMoreListener(new OnLoadMoreListener() {
@Override
public void onLoadMore() {
if (productsArrayList.size() <= 40) {
swipeRefreshLayout.setRefreshing(true);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
fetchOnLoad();
mainActivityAdapter.notifyDataSetChanged();
mainActivityAdapter.setLoaded();
swipeRefreshLayout.setRefreshing(false);
}
}, 1500);
} else {
Toast.makeText(mActivity, "More products coming soon", Toast.LENGTH_SHORT).show();
}
}
});
//Code for this provided above
mainActivityAdapter.setOnRefreshMoreListener(new OnRefreshMoreListener() {});
}
}
//Code for this provided above
public void fetchOnLoad() {}
}
【问题讨论】:
-
fetchOnLoad()的post code;
-
添加在上面。谢谢。
标签: android android-recyclerview notifydatasetchanged fresco