I have a problem, when i swipe to refresh the data, the first swipe is ok but after that every swipe reload and add the same data over and over again, by the end i have a list with same items over and over... I'm using a loader.
I tried to clear before but i don't understand what's wrong with my code, if someone could explain it to me. Thank You.
Here my code :
public abstract class NewsFragment extends Fragment implements LoaderManager.LoaderCallbacks<ArrayList<Articles>> {
protected ItemAdapter mArticleAdapter;
protected RecyclerView mRecyclerView;
protected NewsFragment.OnNewSelectedInterface mListener;
protected RecyclerView.LayoutManager mManager;
protected SwipeRefreshLayout mSwipeRefreshLayout;
protected LoaderManager mLoaderManager;
private boolean mStateSaved;
private static final int NEWS_LOAD_ID = 1;
public static final String KEY_LIST = "key_list";
public interface OnNewSelectedInterface {
void onListNewSelected(int index, ArrayList<Articles> articles);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.list_present_news, container, false);
mListener = (NewsFragment.OnNewSelectedInterface) getActivity();
mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeContainer);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerview);
mManager = new LinearLayoutManager(getActivity());
mArticleAdapter = new ItemAdapter(getActivity(), new ArrayList<Articles>(), mListener);
mLoaderManager = getLoaderManager();
mStateSaved = mArticleAdapter.isStateSaved();
mRecyclerView.setAdapter(mArticleAdapter);
mRecyclerView.setLayoutManager(mManager);
getData();
refreshData();
if(!isNetworkAvailable())alertUserAboutError();
setDivider();
return view;
}
private void setDivider() {
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mRecyclerView
.getContext(), DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(dividerItemDecoration);
}
private void getData() {
getLoaderManager().initLoader(NEWS_LOAD_ID, null, this).forceLoad();
}
private void alertUserAboutError() {
AlertDialogFragment alertDialogFragment = new AlertDialogFragment();
alertDialogFragment.show(getActivity().getFragmentManager(), "error_dialog");
}
protected abstract String[] getUrl();
private boolean isNetworkAvailable() {
ConnectivityManager manager = (ConnectivityManager)
getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = manager.getActiveNetworkInfo();
boolean isAvailable = false;
if (networkInfo != null && networkInfo.isConnected()) {
isAvailable = true;
}
return isAvailable;
}
private void refreshData() {
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
mArticleAdapter.clear();
mSwipeRefreshLayout.setRefreshing(false);
}
});
mSwipeRefreshLayout.setColorSchemeResources(
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
}
#Override
public Loader<ArrayList<Articles>> onCreateLoader(int id, Bundle args) {
return new NewsLoader(getActivity(), getUrl());
}
#Override
public void onLoadFinished(Loader<ArrayList<Articles>> loader, ArrayList<Articles> data) {
if (data != null && !data.isEmpty()) {
mArticleAdapter.addAll(data);
}
}
#Override
public void onLoaderReset(Loader<ArrayList<Articles>> loader) {
mArticleAdapter.clear();
}
}
My loader class :
public class NewsLoader extends AsyncTaskLoader<ArrayList<Articles>>{
private ArrayList<Articles> mArticlesArrayList;
private String[] mUrl;
public NewsLoader(Context context, String[] url) {
super(context);
mUrl = url;
}
#Override
public ArrayList<Articles> loadInBackground() {
OkHttpClient mClient = new OkHttpClient();
for (String aMUrl : mUrl) {
Request mRequest = new Request.Builder().url(aMUrl).build();
try {
Response response = mClient.newCall(mRequest).execute();
try {
if (response.isSuccessful()) {
String json = response.body().string();
getMultipleUrls(json);
}
} catch (IOException | JSONException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return mArticlesArrayList;
}
private void getMultipleUrls(String jsonData) throws JSONException {
if (mArticlesArrayList == null) {
mArticlesArrayList = getArticleForecast(jsonData);
} else {
mArticlesArrayList.addAll(getArticleForecast(jsonData));
}
}
private ArrayList<Articles> getArticleForecast(String jsonData) throws JSONException {
JSONObject forecast = new JSONObject(jsonData);
JSONArray articles = forecast.getJSONArray("articles");
ArrayList<Articles> listArticles = new ArrayList<>(articles.length());
for (int i = 0; i < articles.length(); i++) {
JSONObject jsonArticle = articles.getJSONObject(i);
Articles article = new Articles();
String urlImage = jsonArticle.getString("urlToImage");
article.setTitle(jsonArticle.getString("title"));
article.setDescription(jsonArticle.getString("description"));
article.setImageView(urlImage);
article.setArticleUrl(jsonArticle.getString("url"));
listArticles.add(i, article);
}
return listArticles;
}
}
My Adapter class :
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ArticleViewHolder> {
private static final String TAGO = ItemAdapter.class.getSimpleName();
private final NewsFragment.OnNewSelectedInterface mListener;
private ArrayList<Articles> mArticlesList;
private Context mContext;
private int lastPosition = -1;
private boolean mStateSaved = false;
public boolean isStateSaved() {
return mStateSaved;
}
public void setStateSaved(boolean stateSaved) {
mStateSaved = stateSaved;
}
public ItemAdapter(Context context, ArrayList<Articles> articles, NewsFragment.OnNewSelectedInterface listener){
mContext = context;
mArticlesList = articles;
mListener = listener;
}
#Override
public ArticleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_card_view, parent, false);
ArticleViewHolder articleViewHolder = new ArticleViewHolder(view);
articleViewHolder.setIsRecyclable(false);
return articleViewHolder;
}
#Override
public void onBindViewHolder(ArticleViewHolder holder, int position) {
holder.bindArticle(mArticlesList.get(holder.getAdapterPosition()));
setAnimation(holder.itemView, holder.getAdapterPosition());
}
private void setAnimation(View viewToAnimate, int position) {
if (position > lastPosition) {
Animation animation = AnimationUtils.loadAnimation(viewToAnimate.getContext(), android.R.anim.slide_in_left);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
#Override
public int getItemCount() {
return mArticlesList.size();
}
public void clear() {
mArticlesList.clear();
notifyDataSetChanged();
}
public void addAll(ArrayList<Articles> articles) {
mArticlesList.addAll(articles);
notifyDataSetChanged();
}
protected class ArticleViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private ImageView mImageView;
private TextView mTitleTextView, mDescriptionTextView;
private FloatingActionButton mSaveButton;
private ArticleViewHolder(View itemView) {
super(itemView);
mImageView = (ImageView) itemView.findViewById(R.id.photoImageView);
mTitleTextView = (TextView) itemView.findViewById(R.id.titleWithoutImage);
mDescriptionTextView = (TextView) itemView.findViewById(R.id.descriptionTextView);
mSaveButton = (FloatingActionButton) itemView.findViewById(R.id.floatingActionButton);
itemView.setOnClickListener(this);
}
private void bindArticle(final Articles article) {
Glide.with(mContext).load(article.getImageView()).into(mImageView);
mTitleTextView.setText(article.getTitle());
mDescriptionTextView.setText(article.getDescription());
if(mDescriptionTextView.getText().equals("")){
mDescriptionTextView.setVisibility(View.GONE);
}
mSaveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
insertArticle(article);
article.setStateSaved(true);
}
});
Log.v(TAGO, "Item id : " + getItemId()
+ "Item count : " + getItemCount()
+ "Item position : " + getAdapterPosition()
+ String.valueOf(article.isStateSaved()));
}
private void insertArticle(Articles articles) {
String title = articles.getTitle();
String description = articles.getDescription();
String url = articles.getArticleUrl();
ContentValues contentValues = new ContentValues();
contentValues.put(ArticleContract.ArticleEntry.COLUMN_TITLE_ARTICLE, title);
contentValues.put(ArticleContract.ArticleEntry.COLUMN_DESCRIPTION_ARTICLE, description);
contentValues.put(ArticleContract.ArticleEntry.COLUMN_URL_ARTICLE, url);
Uri uri = mContext.getContentResolver().insert(ArticleContract.ArticleEntry.CONTENT_URI, contentValues);
if(uri == null) {
Log.v(TAGO, "Error");
} else Toast.makeText(mContext, "Article Saved", Toast.LENGTH_SHORT).show();
}
#Override
public void onClick(View view) {
mListener.onListNewSelected(getLayoutPosition(), mArticlesList);
}
}
}
You are using ViewHolder#setIsRecyclable incorrectly; this method is meant to be used to prevent a ViewHolder from being recycled only while changes are being made to it. According to the documentation:
Calls to setIsRecyclable() should always be paired (one call to
setIsRecyclabe(false) should always be matched with a later call to
setIsRecyclable(true)).
This means none of your ViewHolder objects will be recycled, effectively making the use of a RecyclerView worthless, and preventing it from reusing the views when you attempt to bind new objects to your RecyclerView.
So, in short, remove that line of code.
I noticed a few other small issues with your adapter code as well, which can cause a multitude headaches in the future; so I took the liberty of highlighting some of the changes I would make.
Just for my own sanity, I will refer to your Articles class as Article.
It is usually not a good idea to pass around your Context all over the place. The View passed to your ViewHolder already has a reference to a Context, so you can use that instead.
As for the insertArticle() code, the Activity should be handling this anyway. So you can pass the Article back to the Activity by passing a listener to your Adapter (and subsequently, each ViewHolder) instead of the Context.
You should also consider using the DiffUtil class instead of just calling notifyDataSetChanged(); it is much more efficient. Just make sure your Article class is implementing equals() and hashCode() or it will not work.
I didn't include the animation code (that can easily be added back in) or the saved state code (mostly because I don't know what you were trying to do).
public class ArticleAdapter extends RecyclerView.Adapter<Article> {
private List<Article> mData;
private ArticleViewHolder.OnSelectedListener mOnSelectedListener;
private ArticleViewHolder.OnSaveListener mOnSaveListener;
public ArticleAdapter(ArticleViewHolder.OnSelectedListener onSelectedListener, ArticleViewHolder.OnSaveListener onSaveListener) {
mOnSelectedListener = onSelectedListener;
mOnSaveListener = onSaveListener;
mData = new ArrayList<>();
}
public void replaceData(final List<Article> data) {
final List<Article> oldData = new ArrayList<>(mData);
mData.clear();
if (data != null) {
mData.addAll(data);
}
DiffUtil.calculateDiff(new DiffUtil.Callback() {
#Override
public int getOldListSize() {
return oldData.size();
}
#Override
public int getNewListSize() {
return mData.size();
}
#Override
public int areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldData.get(oldItemPosition).equals(mData.get(newItemPosition));
}
#Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldData.get(oldItemPosition).equals(mData.get(newItemPosition));
}
}).dispatchUpdatesTo(this);
}
#Override
public ArticleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_card_view, parent, false);
return new SelectLocationViewHolder(view, mOnSelectedListener, mOnSaveListener);
}
#Override
public void onBindViewHolder(ArticleViewHolder holder, int position) {
holder.bind(mData.get(position));
}
#Override
public int getItemCount() {
return mData.size();
}
}
public class ArticleViewHolder extends RecyclerView.ViewHolder {
public interface OnSelectedListener {
void onSelected(Article article);
}
public interface OnSaveListener {
void onSave(Article article);
}
private View mView;
private Article mArticle;
private OnSelectedListener mOnSelectedListener;
private OnSaveListener mOnSaveListener;
private ImageView mImageView;
private TextView mTitleTextView, mDescriptionTextView;
private FloatingActionButton mSaveButton;
public ArticleViewHolder(View itemView, final OnSelectedListener onSelectedListener, final OnSaveListener onSaveListener) {
super(itemView);
mImageView = (ImageView) itemView.findViewById(R.id.photoImageView);
mTitleTextView = (TextView) itemView.findViewById(R.id.titleWithoutImage);
mDescriptionTextView = (TextView) itemView.findViewById(R.id.descriptionTextView);
mSaveButton = (FloatingActionButton) itemView.findViewById(R.id.floatingActionButton);
mView = itemView;
mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onSelectedListener.onSelected(mArticle);
}
});
mSaveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onSaveListener.onSave(mArticle);
}
});
}
public void bind(Article article) {
mArticle = article;
mTitleTextView.setText(article.getTitle());
mDescriptionTextView.setText(article.getDescription());
if(TextUtils.isEmpty(article.getDescription())) {
mDescriptionTextView.setVisibility(View.GONE);
}
Glide.with(mView.getContext()).load(article.getImage()).into(mImageView);
}
}
Edit
The actual issue is that your loader uses the same ArrayList every time, and keeps adding the new results to it.
public class NewsLoader extends AsyncTaskLoader<List<Article>> {
private final String[] mUrls;
private final OkHttpClient mClient;
public NewsLoader(Context context, OkHttpClient client, String... urls) {
super(context);
mClient = client;
mUrls = urls;
}
#Override
public List<Article> loadInBackground() {
List<Article> articles = new ArrayList<>();
for (String url : mUrls) {
Request request = new Request.Builder().url(url).build();
try {
Response response = mClient.newCall(request).execute();
if (response.isSuccessful()) {
parseData(response.body().string(), articles);
}
} catch (IOException | JSONException e) {
e.printStackTrace();
}
}
return articles;
}
private void parseData(List<Article> articles, String data) throws JSONException {
JSONObject forecast = new JSONObject(data);
JSONArray a = forecast.getJSONArray("articles");
for (int i = 0; i < a.length(); i++) {
JSONObject o = a.getJSONObject(i);
Article article = new Article(
o.getString("title"),
o.getString("description"),
o.getString("url"),
o.getString("urlToImage"));
articles.add(article);
}
}
}
Also, you may have noticed, I made a small change to your Article constructor. You should consider making the Article class immutable, as this will prevent you from making mistakes when dealing with multithreading. It should look something like this:
public class Article {
private final String mTitle;
private final String mDescription;
private final String mUrl;
private final String mImageUrl;
public Article(String title, String description, String url, String imageUrl) {
mTitle = title;
mDescription = description;
mUrl = url;
mImageUrl = imageUrl;
}
public String title() {
return mTitle;
}
public String description() {
return mDescription;
}
public String url() {
return mUrl;
}
public String imageUrl() {
return mImageUrl;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Article other = (Article) o;
return mTitle != null && mTitle.equals(other.mTitle) &&
mDescription != null && mDescription.equals(other.mDescription) &&
mUrl != null && mUrl.equals(other.mUrl) &&
mImageUrl != null && mImageUrl.equals(other.mImageUrl);
}
#Override
public int hashCode() {
int result = mTitle != null ? mTitle.hashCode() : 0;
result = 31 * result + (mDescription != null ? mDescription.hashCode() : 0);
result = 31 * result + (mUrl != null ? mUrl.hashCode() : 0);
result = 31 * result + (mImageUrl != null ? mImageUrl.hashCode() : 0);
return result;
}
}
#Override
public void onBindViewHolder(ArticleViewHolder holder, int position) {
holder.bindArticle(mArticlesList.get(position));
setAnimation(holder.itemView, position);
}
public void addAll(ArrayList<Articles> articles) {
mArticlesList.clear();
mArticlesList.addAll(articles);
notifyDataSetChanged();
}
If this doesn't wrok then I think your api is giving you redundant data.
Why you are using articleViewHolder.setIsRecyclable(false);
One another place which might cause the problem is
private void getMultipleUrls(String jsonData) throws JSONException {
if (mArticlesArrayList == null) {
mArticlesArrayList = getArticleForecast(jsonData);
} else {
mArticlesArrayList.addAll(getArticleForecast(jsonData));
}
}
You are calling it from a loop add adding data to your arraylist. There somehow multiple data can be inserted in your ArrayList
Related
I am using Epoxy Controller for Recycler View. I am having trouble changing the view after data changed by the user action.
Basically I have a switch button in a view which is used inside a recycler view and I am trying to update the view on switch button state change. I am calling requestModelBuild() in setProductList() function of the epoxy controller but change is not reflected in the view.
public class SellerInventoryListEpoxyController extends EpoxyController {
private List<Product> productList = Collections.emptyList();
private Context context;
private SellerInventoryListEpoxyController.Callbacks callbacks;
public void setProductList(List<Product> productList, Context context, SellerInventoryListEpoxyController.Callbacks callbacks) {
this.productList = productList;
this.context = context;
this.callbacks = callbacks;
requestModelBuild();
}
#Override
protected void buildModels() {
for (int i = 0; i < productList.size(); i++) {
new InventoryProductDetailModel_()
.id(productList.get(i).getId())
.product(productList.get(i))
.position(i)
.listSize(productList.size())
.callbacks(callbacks)
.context(context)
.addTo(this);
}
}
public interface Callbacks {
void onViewComboClick(Product productComboList);
void onProductListingStatusChanged(Boolean newStatus, int productSellerId);
void onRecyclerViewReachEnd();
}
}
public class InventoryProductDetailModel extends EpoxyModelWithHolder<InventoryProductDetailModel.ViewHolder> implements CompoundButton.OnCheckedChangeListener {
#EpoxyAttribute
Product product;
#EpoxyAttribute
int position;
#EpoxyAttribute
int listSize;
#EpoxyAttribute
Context context;
#EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
SellerInventoryListEpoxyController.Callbacks callbacks;
#Override
protected ViewHolder createNewHolder() {
return new ViewHolder();
}
#Override
protected int getDefaultLayout() {
return R.layout.inventroy_item_layout;
}
private DrawableCrossFadeFactory factory =
new DrawableCrossFadeFactory.Builder().setCrossFadeEnabled(true).build();
#Override
public void bind(#NonNull InventoryProductDetailModel.ViewHolder holder) {
super.bind(holder);
holder.quantity.setText(String.format("Available :%d", product.getTotalStock()));
holder.brand.setText(product.getProduct().getBrandName());
holder.title.setText(product.getProduct().getTitle());
holder.category.setText(product.getProduct().getCategoryName());
holder.sku.setText(String.format("Sku: %s", product.getSku()));
holder.inventoryItemConstrainLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, ProductDetailActivity.class);
intent.putExtra("product_id", product.getId());
context.startActivity(intent);
}
});
if (product.getProductCombos() != null && product.getProductCombos().size() > 0) {
holder.variationCount.setVisibility(View.GONE);
holder.comboBtn.setVisibility(View.VISIBLE);
holder.comboBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
callbacks.onViewComboClick(product);
}
});
}
if (product.getSellerActive()) {
holder.productStatusSwitch.setText("Active");
holder.productStatusSwitch.setOnCheckedChangeListener(null);
holder.productStatusSwitch.setChecked(true);
holder.productStatusSwitch.setOnCheckedChangeListener(this);
holder.productStatusSwitch.setTextColor(context.getResources().getColor(R.color.colorAccent));
} else {
holder.productStatusSwitch.setText("Inactive");
holder.productStatusSwitch.setOnCheckedChangeListener(null);
holder.productStatusSwitch.setChecked(false);
holder.productStatusSwitch.setOnCheckedChangeListener(this);
holder.productStatusSwitch.setTextColor(Color.parseColor("#ff0000"));
}
holder.variationCount.setText(format("Variation(%d)", product.getVariantCount()));
holder.variationCount.setVisibility(View.VISIBLE);
holder.comboBtn.setVisibility(View.GONE);
loadImage(holder.productImage, Utils.getRequiredUrlForThisImage(holder.productImage, product.getProduct().getImage()));
if (position == listSize - 2) {
callbacks.onRecyclerViewReachEnd();
}
}
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
callbacks.onProductListingStatusChanged(isChecked, product.getId());
}
private void loadImage(ImageView imageView, String url) {
Glide.with(imageView.getContext()).asBitmap()
.load(Utils.getRequiredUrlForThisImage(imageView, url))
.apply(new RequestOptions().diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
.fitCenter())
.transition(withCrossFade(factory))
.placeholder(R.mipmap.product)
.into(imageView);
}
#Override
public void unbind(#NonNull InventoryProductDetailModel.ViewHolder holder) {
super.unbind(holder);
}
public static class ViewHolder extends EpoxyHolder {
TextView quantity, brand, title, category, variationCount, comboBtn;
ImageView productImage, btn_product_detail;
ProgressBar progressBar;
ConstraintLayout inventoryItemConstrainLayout;
private TextView sku;
private Switch productStatusSwitch;
#Override
protected void bindView(#NonNull View itemView) {
productStatusSwitch = itemView.findViewById(R.id.productStatusSwitch);
quantity = itemView.findViewById(R.id.product_qty);
brand = itemView.findViewById(R.id.product_brand);
title = itemView.findViewById(R.id.product_title);
sku = itemView.findViewById(R.id.sku);
category = itemView.findViewById(R.id.product_category);
variationCount = itemView.findViewById(R.id.variantCount);
productImage = itemView.findViewById(R.id.product_image);
btn_product_detail = itemView.findViewById(R.id.btn_product_detail);
inventoryItemConstrainLayout = itemView.findViewById(R.id.inventory_item_constrain_layout);
comboBtn = itemView.findViewById(R.id.combo_btn);
progressBar = itemView.findViewById(R.id.progressbar);
progressBar.setVisibility(View.GONE);
}
}
#Override
public int hashCode() {
super.hashCode();
return product.hashCode();
}
#Override
public boolean equals(Object o) {
return super.equals(o);
}
}
private void addProductListingChangeObserver(final Boolean newStatus, final int productSellerId) {
ProductUpdate productUpdate = new ProductUpdate();
productUpdate.setSellerActive(newStatus);
mInventoryViewModel.updateProductSeller(productSellerId, productUpdate).observe(this, new Observer<Resource<ProductSeller>>() {
#Override
public void onChanged(Resource<ProductSeller> productSellerResource) {
if (productSellerResource.status == Status.ERROR) {
progressBar.setVisibility(View.GONE);
} else if (productSellerResource.status == Status.SUCCESS) {
progressBar.setVisibility(View.GONE);
if (productSellerResource.data != null && productSellerResource.data.isSellerActive() == newStatus) {
for (int i = 0; i < productList.size(); i++) {
if (productList.get(i).getId() == productSellerId) {
productList.get(i).setSellerActive(newStatus);
break;
}
}
sellerInventoryListEpoxyController.setProductList(productList, getContext(), InventoryFragment.this);
}
} else {
progressBar.setVisibility(View.VISIBLE);
}
}
});
}
In addProductListingChangeObserver() function one object of productList is modified and new productList is passed to the EpoxyController and requestModelbuild is called but the view is not modifying as expected.
TestListModel.class
public class TestListModel {
private String testlist_id;
private String test_price;
private String test_name;
private boolean isSelected;
public TestListModel(String testlist_id, String test_price, String test_name,boolean isSelected) {
this.testlist_id = testlist_id;
this.test_price = test_price;
this.test_name = test_name;
this.isSelected = isSelected;
}
public String getTestlist_id() {
return testlist_id;
}
public void setTestlist_id(String testlist_id) {
this.testlist_id = testlist_id;
}
public String getTest_price() {
return test_price;
}
public void setTest_price(String test_price) {
this.test_price = test_price;
}
public String getTest_name() {
return test_name;
}
public void setTest_name(String test_name) {
this.test_name = test_name;
}
public boolean isSelected() {
return isSelected;
}
public void setSelected(boolean isSelected) {
this.isSelected = isSelected;
}
}
JsonResponse.java
public class JSONResponse {
private TestListModel[] result;
public TestListModel[] getResult() {
return result;
}
public void setResult(TestListModel[] result) {
this.result = result;
}
}
HealthActivity.java
public class HealthServicesActivity extends AppCompatActivity implements View.OnClickListener {
/*
*Api call
* */
private RecyclerView recyclerView;
private ArrayList<TestListModel> data;
private RecyclerAdapter madapter;
private Button submitButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_health_services);
ButterKnife.bind(this);
sharePreferenceManager = new SharePreferenceManager<>(getApplicationContext());
submitButton=(Button) findViewById(R.id.submit_button);
showcenterid(sharePreferenceManager.getUserLoginData(LoginModel.class));
initViews();
submitButton.setOnClickListener(this);
/*
* On Click Listner
* */
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.submit_button:
int totalAmount = 0;
int totalPrice = 0;
String testName = "";
String testPrice="";
int count = 0;
List<TestListModel> stList = ((RecyclerAdapter) madapter)
.getTestList();
for (int i = 0; i < stList.size(); i++) {
TestListModel singleStudent = stList.get(i);
//AmountCartModel serialNumber = stList.get(i);
if (singleStudent.isSelected() == true) {
testName = testName + "\n" + singleStudent.getTest_name().toString();
testPrice = testPrice+"\n" + singleStudent.getTest_price().toString();
count++;
totalAmount = Integer.parseInt(stList.get(i).getTest_price());
totalPrice = totalPrice + totalAmount;
}
}
Toast.makeText(HealthServicesActivity.this,
"Selected Lists: \n" + testName+ "" + testPrice, Toast.LENGTH_LONG)
.show();
Intent in= new Intent(HealthServicesActivity.this, AmountCartActivity.class);
in.putExtra("test_name", testName);
in.putExtra("test_price", testPrice);
//in.putExtra("total_price",totalPrice);
in.putExtra("total_price", totalPrice);
in.putExtra("serialNumber", count);
startActivity(in);
finish();
break;
/** back Button Click
* */
case R.id.back_to_add_patient:
startActivity(new Intent(getApplicationContext(), PatientActivity.class));
finish();
break;
default:
break;
}
}
/** show center Id in action bar
* */
#Override
protected void onResume() {
super.onResume();
showcenterid(sharePreferenceManager.getUserLoginData(LoginModel.class));
}
private void showcenterid(LoginModel userLoginData) {
centerId.setText(userLoginData.getResult().getGenCenterId());
centerId.setText(userLoginData.getResult().getGenCenterId().toUpperCase());
deviceModeName.setText(userLoginData.getResult().getDeviceModeName());
}
private void initViews() {
recyclerView = (RecyclerView)findViewById(R.id.test_list_recycler_view);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(layoutManager);
loadJSON();
}
private void loadJSON() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(" http://192.168.1.80/aoplnew/api/")
//
.baseUrl("https://earthquake.usgs.gov/fdsnws/event/1/query?")
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiInterface request = retrofit.create(ApiInterface.class);
Call<JSONResponse> call = request.getTestLists();
call.enqueue(new Callback<JSONResponse>() {
#Override
public void onResponse(Call<JSONResponse> call, Response<JSONResponse> response) {
JSONResponse jsonResponse = response.body();
data = new ArrayList<>(Arrays.asList(jsonResponse.getResult()));
madapter = new RecyclerAdapter(data);
recyclerView.setAdapter(madapter);
}
#Override
public void onFailure(Call<JSONResponse> call, Throwable t) {
Log.d("Error",t.getMessage());
}
});
}
HealthRecyclerAdapter.java
public class RecyclerAdapter extends
RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private ArrayList<TestListModel> android;
public RecyclerAdapter(ArrayList<TestListModel> android) {
this.android = android;
}
#Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.test_list_row,parent,false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(RecyclerAdapter.ViewHolder holder, final int position) {
holder.test_name.setText(android.get(position).getTest_name());
holder.test_price.setText(android.get(position).getTest_price());
holder.chkSelected.setChecked(android.get(position).isSelected());
holder.chkSelected.setTag(android.get(position));
holder.chkSelected.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
TestListModel contact = (TestListModel) cb.getTag();
contact.setSelected(cb.isChecked());
android.get(position).setSelected(cb.isChecked());
Toast.makeText(
v.getContext(),
"Clicked on Checkbox: " + cb.getText() + " is " + cb.isChecked(), Toast.LENGTH_LONG).show();
}
});
}
#Override
public int getItemCount() {
return android.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView test_name;
private TextView test_price;
public CheckBox chkSelected;
public TestListModel testLists;
public ViewHolder(View itemView) {
super(itemView);
test_name = (TextView)itemView.findViewById(R.id.test_name);
test_price = (TextView)itemView.findViewById(R.id.price_name);
chkSelected = (CheckBox) itemView.findViewById(R.id.check_box);
}
}
// method to access in activity after updating selection
public List<TestListModel> getTestList() {
return android;
}
AmountCartModel.java
public class AmountCartModel {
private String testName;
private String testPrice;
private Integer serialNumber;
private Integer totalPrice;
public AmountCartModel() {
this.testName = testName;
this.testPrice = testPrice;
this.serialNumber = serialNumber;
this.totalPrice = totalPrice;
}
public String getTestName() {
return testName;
}
public void setTestName(String testName) {
this.testName = testName;
}
public String getTestPrice() {
return testPrice;
}
public void setTestPrice(String testPrice) {
this.testPrice = testPrice;
}
public Integer getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(Integer serialNumber) {
this.serialNumber = serialNumber;
}
public Integer getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(Integer totalPrice) {
this.totalPrice = totalPrice;
}
}
AmountCartActivity.java
public class AmountCartActivity extends AppCompatActivity implements View.OnClickListener {
#BindView(R.id.total_price)
TextView totalPriceDisplay;
SharePreferenceManager<LoginModel> sharePreferenceManager;
private RecyclerView recyclerView;
List<AmountCartModel> mydataList ;
private MyAdapter madapter;
Bundle extras ;
String testName="";
String testPrice="";
String totalPrice= "";
int counting = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_amount_cart);
ButterKnife.bind(this);
sharePreferenceManager = new SharePreferenceManager<>(getApplicationContext());
showcenterid(sharePreferenceManager.getUserLoginData(LoginModel.class));
mydataList = new ArrayList<>();
/*
* Getting Values From BUNDLE
* */
extras = getIntent().getExtras();
if (extras != null) {
testName = extras.getString("test_name");
testPrice = extras.getString("test_price");
totalPrice = String.valueOf(extras.getInt("total_price"));
counting = extras.getInt("serialNumber");
//Just add your data in list
AmountCartModel mydata = new AmountCartModel(); // object of Model Class
mydata.setTestName(testName );
mydata.setTestPrice(testPrice);
mydata.setTotalPrice(Integer.valueOf(totalPrice));
mydata.setSerialNumber(counting);
mydataList.add(mydata);
//totalPriceDisplay.setText(totalPrice);
}
madapter=new MyAdapter(mydataList);
madapter.setMyDataList(mydataList);
recyclerView = (RecyclerView)findViewById(R.id.recyler_amount_cart);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(madapter);
RecyclerAdapter.java //RecyclerAdapter for AmountCart
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>
{
private List<AmountCartModel> context;
private List<AmountCartModel> myDataList;
public MyAdapter(List<AmountCartModel> context) {
this.context = context;
myDataList = new ArrayList<>();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
// Replace with your layout
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.amount_cart_row, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// Set Your Data here to yout Layout Components..
// to get Amount
/* myDataList.get(position).getTestName();
myDataList.get(position).getTestPrice();*/
holder.testName.setText(myDataList.get(position).getTestName());
holder.testPrice.setText(myDataList.get(position).getTestPrice());
holder.textView2.setText(myDataList.get(position).getSerialNumber());
}
#Override
public int getItemCount() {
/*if (myDataList.size() != 0) {
// return Size of List if not empty!
return myDataList.size();
}
return 0;*/
return myDataList.size();
}
public void setMyDataList(List<AmountCartModel> myDataList) {
// getting list from Fragment.
this.myDataList = myDataList;
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView testName,testPrice,textView2;
public ViewHolder(View itemView) {
super(itemView);
// itemView.findViewById
testName=itemView.findViewById(R.id.test_name_one);
testPrice=itemView.findViewById(R.id.test_price);
textView2=itemView.findViewById(R.id.textView2);
}
}
}
#Override
public void onBackPressed() {
super.onBackPressed();
startActivity(new
Intent(AmountCartActivity.this,HealthServicesActivity.class));
finish();
}
}
This is my code.
Here I am taking HealthActivity and in this class by using recycler view I have displayed testList in recycler view. I am passing testList whichever I am selecting through checkbox to AmountCartActivity of recycler View, And, I am calculating total amount of the selected testList and I am getting the result and that result I am passing to the AmountCart Activity through bundle and I am getting correct result in bundle, but, when I am trying to display total amount in a textView its showing me nothing.
And, my second problem is,
I am trying to display serial number to to my AmountCartActivity of recycler view whichever I am selecting from previous HealthCartActivity using checkbox. And, I have implemented some code but I am not getting how to solve it. please help me.
For Issue#1
Data should be passed onto the Adapter through constructor. The issue could simply be adding another parameter to the constructor:
public MyAdapter(List<AmountCartModel> context, List<AmountCartModel> myDataList) {
this.context = context;
myDataList = this.myDataList;
}
Or,
To add selection support to a RecyclerView instance:
Determine which selection key type to use, then build a ItemKeyProvider.
Implement ItemDetailsLookup: it enables the selection library to access information about RecyclerView items given a MotionEvent.
Update item Views in RecyclerView to reflect that the user has selected or unselected it.
The selection library does not provide a default visual decoration for the selected items. You must provide this when you implement onBindViewHolder() like,
In onBindViewHolder(), call setActivated() (not setSelected()) on the View object with true or false (depending on if the item is selected).
Update the styling of the view to represent the activated status.
For Issue #2
Try using passing data through intents.
The easiest way to do this would be to pass the serial num to the activity in the Intent you're using to start the activity:
Intent intent = new Intent(getBaseContext(), HealthServicesActivity.class);
intent.putExtra("EXTRA_SERIAL_NUM", serialNum);
startActivity(intent);
Access that intent on next activity
String sessionId= getIntent().getStringExtra("EXTRA_SERIAL_NUM");
In my application I want use two recyclerView into one Activity.
I want when click on items of one of this recylerView's items , add item to another recyclerView.
I write below codes, when click on items just add lasted item info to another recyclerView.
But I want when click on each items, add this each items into another recyclerView not just add lasted items.
Now just add lasted items, but I want click each item add this item.
My Activity code:
public class SuggestFilmActivity extends AppCompatActivity implements SuggestedListener {
#BindView(R.id.toolbarTitleTxt)
TextView toolbarTitleTxt;
#BindView(R.id.suggestFilm_searchEditText)
EditText suggestFilm_searchEditText;
#BindView(R.id.suggestFilm_searchBtn)
ImageView suggestFilm_searchBtn;
#BindView(R.id.suggestFilm_recyclerView)
RecyclerView suggestFilm_recyclerView;
#BindView(R.id.suggestFilm_recyclerViewProgress)
ProgressBar suggestFilm_recyclerViewProgress;
#BindView(R.id.newsPageLoadLay)
RelativeLayout newsPageLoadLay;
#BindView(R.id.suggestFilm_recyclerViewSendUser)
RecyclerView suggestFilm_recyclerViewSendUser;
private Context context;
private SuggestFilmAdapter suggestFilmAdapter;
private SuggestFilmUserAdapter suggestFilmUserAdapter;
private List<Result> model = new ArrayList<>();
private InterfaceApi api;
private SharedPrefrencesHandler prefrencesHandler;
private String token;
private GridLayoutManager gridLayoutManager;
private LinearLayoutManager linearLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_suggest_film);
//Initialize
ButterKnife.bind(this);
context = this;
prefrencesHandler = new SharedPrefrencesHandler(context);
api = ApiClient.getClient().create(InterfaceApi.class);
suggestFilmAdapter = new SuggestFilmAdapter(context, model, this);
gridLayoutManager = new GridLayoutManager(context, 3);
linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
//Get token
token = prefrencesHandler.getFromShared(SharedPrefrencesKeys.TOKEN.name());
//Set toolbar title
toolbarTitleTxt.setText(context.getResources().getString(R.string.SuggestToFollowers));
//Init followers recyclerView
suggestFilm_recyclerView.setLayoutManager(gridLayoutManager);
suggestFilm_recyclerView.setHasFixedSize(true);
//Init send user recyclerView
suggestFilm_recyclerViewSendUser.setLayoutManager(linearLayoutManager);
suggestFilm_recyclerViewSendUser.setHasFixedSize(true);
//Load more
newsPageLoadLay.setVisibility(View.GONE);
suggestFilm_recyclerView.setOnScrollListener(new EndlessRecyclerGridPage1(gridLayoutManager) {
#Override
public void onLoadMore(int current_page) {
newsPageLoadLay.setVisibility(View.VISIBLE);
Call<SeriesWhoWatchedResponse> call = api.getSuggestFilmUsers(token, filmSendData(current_page));
call.enqueue(new Callback<SeriesWhoWatchedResponse>() {
#Override
public void onResponse(Call<SeriesWhoWatchedResponse> call, Response<SeriesWhoWatchedResponse> response) {
if (response.body().getData() != null && response.body().getStatusCode() != 401
&& response.body().getStatusCode() != 402) {
if (response.body().getData().getResult().size() > 0) {
suggestFilmAdapter.addNewItem(response.body().getData().getResult());
//Gone no explore
newsPageLoadLay.setVisibility(View.GONE);
}
} else {
prefrencesHandler.remove(SharedPrefrencesKeys.TOKEN.name());
startActivity(new Intent(context, LoginActivity.class));
}
newsPageLoadLay.setVisibility(View.GONE);
}
#Override
public void onFailure(Call<SeriesWhoWatchedResponse> call, Throwable t) {
newsPageLoadLay.setVisibility(View.GONE);
}
});
}
});
//Get user data
getUserData();
}
private void getUserData() {
suggestFilm_recyclerViewProgress.setVisibility(View.VISIBLE);
Call<SeriesWhoWatchedResponse> call = api.getSuggestFilmUsers(token, filmSendData(1));
call.enqueue(new Callback<SeriesWhoWatchedResponse>() {
#Override
public void onResponse(Call<SeriesWhoWatchedResponse> call, Response<SeriesWhoWatchedResponse> response) {
if (response.body().getData() != null && response.body().getData().getResult().size() > 0
&& response.body().getStatusCode() != 401 && response.body().getStatusCode() != 402) {
model.clear();
model.addAll(response.body().getData().getResult());
suggestFilmAdapter.notifyDataSetChanged();
suggestFilm_recyclerView.setAdapter(suggestFilmAdapter);
} else {
prefrencesHandler.remove(SharedPrefrencesKeys.TOKEN.name());
startActivity(new Intent(context, LoginActivity.class));
}
suggestFilm_recyclerViewProgress.setVisibility(View.GONE);
}
#Override
public void onFailure(Call<SeriesWhoWatchedResponse> call, Throwable t) {
suggestFilm_recyclerViewProgress.setVisibility(View.GONE);
}
});
}
private SuggestFilmSendData filmSendData(int page) {
SuggestFilmSendData sendData = new SuggestFilmSendData();
sendData.setKeyword("");
sendData.setPageIndex(page);
sendData.setPageSize(10);
return sendData;
}
private ArrayList<SuggestFilmAddUser> prepareData(int id, String name, String image) {
ArrayList<SuggestFilmAddUser> suggestFilmAddUserList = new ArrayList<>();
SuggestFilmAddUser suggestFilmAddUser = new SuggestFilmAddUser();
suggestFilmAddUser.setId(id);
suggestFilmAddUser.setName(name);
suggestFilmAddUser.setImage(image);
suggestFilmAddUserList.add(suggestFilmAddUser);
return suggestFilmAddUserList;
}
#Override
public void onSend(int Id, String name, String image) {
ArrayList<SuggestFilmAddUser> suggestFilmAddUserList = prepareData(Id, name, image);
suggestFilmUserAdapter = new SuggestFilmUserAdapter(context, suggestFilmAddUserList);
suggestFilm_recyclerViewSendUser.setAdapter(suggestFilmUserAdapter);
}
}
One recyclerView adapter and send data Interface codes:
public class SuggestFilmAdapter extends RecyclerView.Adapter<SuggestFilmAdapter.ViewHolder> {
private Context context;
private List<Result> model;
private SuggestedListener suggestedListener;
public SuggestFilmAdapter(Context context, List<Result> model, SuggestedListener suggestedListener) {
this.context = context;
this.model = model;
this.suggestedListener = suggestedListener;
}
#Override
public SuggestFilmAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_suggest_film_users_followers, parent, false);
return new SuggestFilmAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(final SuggestFilmAdapter.ViewHolder holder, final int position) {
//Name
holder.row_suggestFilmProfileName.setText(model.get(position).getName());
//Image
Glide.with(context)
.load(model.get(position).getImageUrl())
.asBitmap()
.placeholder(R.drawable.default_image)
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.override(300, 300)
.into(new BitmapImageViewTarget(holder.row_suggestFilmProfileImage) {
#Override
protected void setResource(Bitmap resource) {
if (context == null) return;
RoundedBitmapDrawable circularBitmapDrawable =
RoundedBitmapDrawableFactory.create(context.getResources(), resource);
circularBitmapDrawable.setCircular(true);
holder.row_suggestFilmProfileImage.setImageDrawable(circularBitmapDrawable);
}
});
//Is Mutual
if (model.get(position).getIsMutual()) {
holder.row_suggestFilmIsOk.setVisibility(View.VISIBLE);
} else {
holder.row_suggestFilmIsOk.setVisibility(View.GONE);
}
holder.row_suggestedLay.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
suggestedListener.onSend(model.get(position).getUserId(),
model.get(position).getName(),
model.get(position).getImageUrl());
}
});
}
#Override
public int getItemCount() {
return model.size();
}
public void addNewItem(List<Result> newContent) {
int start = this.model.size();
int end = newContent.size();
model.addAll(newContent);
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private ImageView row_suggestFilmProfileImage, row_suggestFilmIsOk;
private TextView row_suggestFilmProfileName;
private RelativeLayout row_suggestedLay;
public ViewHolder(View itemView) {
super(itemView);
row_suggestFilmProfileImage = (ImageView) itemView.findViewById(R.id.row_suggestFilmProfileImage);
row_suggestFilmIsOk = (ImageView) itemView.findViewById(R.id.row_suggestFilmIsOk);
row_suggestFilmProfileName = (TextView) itemView.findViewById(R.id.row_suggestFilmProfileName);
row_suggestedLay = (RelativeLayout) itemView.findViewById(R.id.row_suggestedLay);
}
}
}
Model class :
public class SuggestFilmAddUser {
private int id;
private String name;
private String image;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
}
How can I it? Please help me
Inside onSend() , you need to add each objects to an arraylist which should be declared globally. Then call notifyItemInserted(arraylist.size()-1) in adapter to refresh recyclerview
public class SuggestFilmActivity ....
{ ArrayList<SuggestFilmAddUser> suggestFilmAddUserList=new ArrayList();
SuggestFilmUserAdapter suggestFilmUserAdapter;
......
......
protected void onCreate(Bundle savedInstance)
{....
....
....
suggestFilmUserAdapter = new SuggestFilmUserAdapter(context,
suggestFilmAddUserList);
suggestFilm_recyclerViewSendUser.setAdapter(suggestFilmUserAdapter);
.....
.....
}
public void onSend(int Id, String name, String image) {
SuggestFilmAddUser suggestFilmAddUser = new SuggestFilmAddUser();
suggestFilmAddUser.setId(id);
suggestFilmAddUser.setName(name);
suggestFilmAddUser.setImage(image);
suggestFilmAddUserList.add(suggestFilmAddUser);
suggestFilmUserAdapter.notifyItemInserted(suggestFilmAddUserList.size()-1)
}
I have an Interface implemented in ProductListAdapter class which is a list adapter. Items in this list have three input fields. to keep track of those values I have implemented a class MyCustomEditTextListener which extends a TextWatcher class. This class simply create array list of edited data. I want to get reference to array list every time it changes from fragment which contains list view. For that I have implemented DataChangedListener
ProductListAdapter.java
public class ProductListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private LayoutInflater inflater;
private ArrayList<Products> listData;
private ArrayList<Products> editedData;
private Context context;
private DataChangedListener dataChangedListener;
private static final int ITEM = 0;
private static final int LOADING = 1;
private static final int QUANTITY = 5;
private static final int FREE_QUANTITY = 10;
private static final int DISCOUNT = 15;
public ProductListAdapter(ArrayList<Products> listData, ArrayList<Products> editedData, Context context) {
this.listData = listData;
this.context = context;
this.editedData = editedData;
inflater = LayoutInflater.from(this.context);
}
public void updateData(ArrayList<Products> data) {
this.listData = data;
notifyDataSetChanged();
}
public void setDataChangedListener(DataChangedListener listener) {
this.dataChangedListener = listener;
}
#Override
public int getItemViewType(int position) {
return listData.get(position) == null ? LOADING : ITEM;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
switch (viewType) {
case ITEM:
viewHolder = getViewHolder(parent, inflater);
break;
case LOADING:
View v2 = inflater.inflate(R.layout.list_footer, parent, false);
viewHolder = new LoadingVH(v2);
break;
}
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Products productObject = listData.get(position);
switch (getItemViewType(position)) {
case ITEM:
for(int i=0; i<editedData.size(); i++){
if(productObject.getProductId().equals(editedData.get(i).getProductId())){
productObject.setQuantity(editedData.get(i).getQuantity());
productObject.setFreeQuantity(editedData.get(i).getFreeQuantity());
productObject.setDiscount(editedData.get(i).getDiscount());
}
}
String productName = productObject.getProductName();
String quantityValue = productObject.getQuantity();
String freeQuantityValue = productObject.getFreeQuantity();
String discountValue = productObject.getDiscount();
String quantityInHand = productObject.getQuantityInHand();
String price = productObject.getWholeSalePrice();
ContentViewHolder movieVH = (ContentViewHolder) holder;
movieVH.productName.setText(productName);
movieVH.stock.setText(quantityInHand);
movieVH.price.setText("Rs."+price);
movieVH.quantityEditTextListener.updatePosition(movieVH.getLayoutPosition());
movieVH.quantity.setText(quantityValue);
movieVH.freeQuantityEditTextListener.updatePosition(movieVH.getLayoutPosition());
movieVH.freeQuantity.setText(freeQuantityValue);
movieVH.discountEditTextListener.updatePosition(movieVH.getLayoutPosition());
movieVH.discount.setText(discountValue);
movieVH.quantity.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
return false;
}
});
break;
case LOADING:
//Do nothing
break;
}
}
#Override
public int getItemCount() {
return listData == null ? 0 : listData.size();
}
#NonNull
private RecyclerView.ViewHolder getViewHolder(ViewGroup parent, LayoutInflater inflater) {
RecyclerView.ViewHolder viewHolder;
View view = inflater.inflate(R.layout.custom_product_list_item, parent, false);
viewHolder = new ContentViewHolder(view, new MyCustomEditTextListener()
, new MyCustomEditTextListener(), new MyCustomEditTextListener());
return viewHolder;
}
/**
* View holder for main container
*/
public class ContentViewHolder extends RecyclerView.ViewHolder{
private TextView productName;
private EditText quantity;
private EditText freeQuantity;
private EditText discount;
private TextView stock;
private TextView price;
private MyCustomEditTextListener quantityEditTextListener;
private MyCustomEditTextListener freeQuantityEditTextListener;
private MyCustomEditTextListener discountEditTextListener;
public ContentViewHolder(View itemView, MyCustomEditTextListener textListener
, MyCustomEditTextListener textListener2, MyCustomEditTextListener textListener3) {
super(itemView);
productName = (TextView) itemView.findViewById(R.id.product_name_data);
quantity = (EditText) itemView.findViewById(R.id.quantity_1_edit_text);
freeQuantity = (EditText) itemView.findViewById(R.id.quantity_2_edit_text);
discount = (EditText) itemView.findViewById(R.id.quantity_3_edit_text);
stock = (TextView) itemView.findViewById(R.id.quantity_in_hand_value);
price = (TextView) itemView.findViewById(R.id.price_value);
quantityEditTextListener = textListener;
quantityEditTextListener.setEditTextType(QUANTITY);
freeQuantityEditTextListener = textListener2;
freeQuantityEditTextListener.setEditTextType(FREE_QUANTITY);
discountEditTextListener = textListener3;
discountEditTextListener.setEditTextType(DISCOUNT);
this.quantity.addTextChangedListener(quantityEditTextListener);
this.freeQuantity.addTextChangedListener(freeQuantityEditTextListener);
this.discount.addTextChangedListener(discountEditTextListener);
}
}
/**
* View holder to display loading list item
*/
protected class LoadingVH extends RecyclerView.ViewHolder {
public LoadingVH(View itemView) {
super(itemView);
}
}
/**
* textWatcher for to keep track of changed data.
*/
private class MyCustomEditTextListener implements TextWatcher {
private int position;
private int type;
public void updatePosition(int position) {
this.position = position;
}
public void setEditTextType(int type) {
this.type = type;
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
// no op
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
if (type == QUANTITY) {
listData.get(position).setQuantity(charSequence.toString());
} else if (type == FREE_QUANTITY) {
listData.get(position).setFreeQuantity(charSequence.toString());
} else if (type == DISCOUNT) {
listData.get(position).setDiscount(charSequence.toString());
}
}
#Override
public void afterTextChanged(Editable s) {
boolean matchFound = false;
if(s.toString().length()>0){
for (int i=0;i<editedData.size();i++){
if(editedData.get(i).getProductId()
.equals(listData.get(position).getProductId())){
matchFound = true;
if (type == QUANTITY) {
editedData.get(i).setQuantity(s.toString());
} else if (type == FREE_QUANTITY) {
editedData.get(i).setFreeQuantity(s.toString());
} else if (type == DISCOUNT) {
editedData.get(i).setDiscount(s.toString());
}
}
}
if(!matchFound){
editedData.add(listData.get(position));
}
if(dataChangedListener!=null){
dataChangedListener.onDataChanged(editedData);
}
}
}
}
public interface DataChangedListener{
void onDataChanged(ArrayList<Products> editedData);
}
In my OrderEditFragment i'm trying to implement that interface to do necessary calculations.
OrderEditFragment.java
public class OrderEditFragment extends Fragment implements ProductListAdapter.DataChangedListener {
private LinearLayoutManager layoutManager;
private RecyclerView productRecyclerView;
private static ProductListAdapter productListAdapter;
private String employeeId;
private static ArrayList<Products> editedData;
private static ArrayList<Products> productsData;
private SharedPreferences sharedpreferences;
private final static OkHttpClient client = new OkHttpClient();
public OrderEditFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View inflate = inflater.inflate(R.layout.fragment_order_edit, container, false);
initComponents(inflate);
return inflate;
}
private void initComponents(View view) {
productRecyclerView = (RecyclerView) view.findViewById(R.id.product_edit_recycler_view);
progressView = (CircularProgressView) view.findViewById(R.id.progress_view);
layoutManager = new LinearLayoutManager(getContext());
sharedpreferences = getActivity().getSharedPreferences("dgFashionPref", Context.MODE_PRIVATE);
employeeId = sharedpreferences.getString("employee_id","");
productsData = new ArrayList<>();
editedData = new ArrayList<>();
isLoading = false;
isLastPage = false;
isFirstLoad = true;
isSearch = false;
new GetProductListGetRequest(getContext(), productRecyclerView, layoutManager)
.execute(RestConnection.PRODUCT_LIST_GET
+ RestConnection.CUSTOMER_ID_FOR_NAME + employeeId);
}
#Override
public void onDataChanged(ArrayList<Products> editedData) {
Log.d(TAG,editedData.toString());
}
/**
* AsyncTask class which handel the GET request to get product list
**/
public static class GetProductListGetRequest extends AsyncTask<String, Void, String>{
private WeakReference<Context> ActivityWeakReference;
private WeakReference<RecyclerView> recyclerViewWeakReference;
private WeakReference<RecyclerView.LayoutManager> layoutManagerWeakReference;
public GetProductListGetRequest(Context activity, RecyclerView recyclerView
, RecyclerView.LayoutManager layoutManager) {
ActivityWeakReference = new WeakReference<>(activity);
recyclerViewWeakReference = new WeakReference<>(recyclerView);
layoutManagerWeakReference = new WeakReference<>(layoutManager);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String urlEndPoint = params[0];
Request request = new Request.Builder()
.url(RestConnection.API_BASE + urlEndPoint)
.build();
try {
Response response = client.newCall(request).execute();
return response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String response) {
if( productsData.size()>0){
productsData.remove(productsData.size() - 1);
}
JSONArray responseBody;
try {
if (response != null && ActivityWeakReference.get() != null) {
responseBody = new JSONArray(response);
for (int i = 0; i < responseBody.length(); i++) {
JSONObject row = responseBody.getJSONObject(i);
String productId = row.getString("ProductID");
String productName = row.getString("Name");
String unit = row.getString("Unit");
String wholeSalePrice = row.getString("WSalePrice");
String packSize = row.getString("PackSize");
String retailPrice = row.getString("RetailPrice");
String costPrice = row.getString("CostPrice");
String qtyInHand = row.getString("QtyInHand");
Products productObj = new Products();
productObj.setProductName(productName);
productObj.setProductId(productId);
productObj.setUnit(unit);
productObj.setWholeSalePrice(wholeSalePrice);
productObj.setPackSize(packSize);
productObj.setRetailPrice(retailPrice);
productObj.setCostPrice(costPrice);
productObj.setQuantityInHand(qtyInHand);
productsData.add(productObj);
}
productListAdapter = new ProductListAdapter(productsData, editedData, ActivityWeakReference.get());
productListAdapter.setDataChangedListener(ActivityWeakReference.get());
recyclerViewWeakReference.get().setAdapter(productListAdapter);
recyclerViewWeakReference.get().setLayoutManager(layoutManagerWeakReference.get());
recyclerViewWeakReference.get().addItemDecoration(new RecyclerViewDivider(2));
} else {
Toast.makeText(ActivityWeakReference.get(), "Can't connect to the server", Toast.LENGTH_LONG).show();
}
} catch (JSONException e)
{
Log.d(TAG, "Get customer details onPostExecute :" + e.getLocalizedMessage());
}
}
}
/**
* A class that define space between list items
*/
private static class RecyclerViewDivider extends RecyclerView.ItemDecoration {
int space;
public RecyclerViewDivider(int space) {
this.space = space;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
outRect.bottom = space;
if (parent.getChildLayoutPosition(view) == 0) {
outRect.top = space;
}
}
}
}
As you can see I'm trying to instantiate interface inside AsyncTask class soon after created productListAdapter object by calling setDataChangedListener(DataChangedListener listener); method. But it did not take ActivityWeakReference.get() as a valid parameter. I have done slimier thing before with list adapter to bring custom created onListItemClick event to activity. In those cases ActivityWeakReference.get() works fine. I think this is happening because I'm in a fragment, But I can't figure out which object I should pass. I need to create Adapter inside AsyncTask because i have implemented pagination for list view. I remove those codes to make this post short. Please help.
Found the solution. You need to pass fragment object to interface not the activity.
Here's my fragment class now.
/**
* AsyncTask class which handel the GET request to get product list
**/
public static class GetProductListGetRequest extends AsyncTask<String, Void, String>{
private WeakReference<OrderEditFragment> fragmentWeakReference;
private WeakReference<RecyclerView> recyclerViewWeakReference;
private WeakReference<RecyclerView.LayoutManager> layoutManagerWeakReference;
public GetProductListGetRequest(OrderEditFragment fragment, RecyclerView recyclerView
, RecyclerView.LayoutManager layoutManager) {
fragmentWeakReference = new WeakReference<>(fragment);
recyclerViewWeakReference = new WeakReference<>(recyclerView);
layoutManagerWeakReference = new WeakReference<>(layoutManager);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String urlEndPoint = params[0];
Request request = new Request.Builder()
.url(RestConnection.API_BASE + urlEndPoint)
.build();
//Log.d(TAG,RestConnection.API_BASE + urlEndPoint);
try {
Response response = client.newCall(request).execute();
return response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String response) {
if( productsData.size()>0){
productsData.remove(productsData.size() - 1);
}
JSONArray responseBody;
//Log.d(TAG,response);
try {
if (response != null && fragmentWeakReference.get() != null) {
responseBody = new JSONArray(response);
for (int i = 0; i < responseBody.length(); i++) {
JSONObject row = responseBody.getJSONObject(i);
String productId = row.getString("ProductID");
String productName = row.getString("Name");
String unit = row.getString("Unit");
String wholeSalePrice = row.getString("WSalePrice");
String packSize = row.getString("PackSize");
String retailPrice = row.getString("RetailPrice");
String costPrice = row.getString("CostPrice");
String qtyInHand = row.getString("QtyInHand");
Products productObj = new Products();
productObj.setProductName(productName);
productObj.setProductId(productId);
productObj.setUnit(unit);
productObj.setWholeSalePrice(wholeSalePrice);
productObj.setPackSize(packSize);
productObj.setRetailPrice(retailPrice);
productObj.setCostPrice(costPrice);
productObj.setQuantityInHand(qtyInHand);
productsData.add(productObj);
}
/** if lower limit and upper limit change, change responseBody.length()<10 respectively **/
if (responseBody.length() == 0 || responseBody.length() < 10) {
isLastPage = true;
}
if (isFirstLoad) {
progressView.setVisibility(View.GONE);
recyclerViewWeakReference.get().setVisibility(View.VISIBLE);
productListAdapter = new ProductListAdapter(productsData, editedData, fragmentWeakReference.get().getContext());
productListAdapter.setDataChangedListener(fragmentWeakReference.get());
recyclerViewWeakReference.get().setAdapter(productListAdapter);
recyclerViewWeakReference.get().setLayoutManager(layoutManagerWeakReference.get());
recyclerViewWeakReference.get().addItemDecoration(new RecyclerViewDivider(2));
isFirstLoad = false;
} else {
productListAdapter.updateData(productsData);
isLoading = false;
}
} else {
Toast.makeText(fragmentWeakReference.get().getContext(), "Can't connect to the server", Toast.LENGTH_LONG).show();
}
} catch (JSONException e)
{
Log.d(TAG, "Get customer details onPostExecute :" + e.getLocalizedMessage());
}
}
}
And create AsyncTask object like bellow.
new GetProductListGetRequest(this, productRecyclerView, layoutManager)
.execute(RestConnection.PRODUCT_LIST_GET
+ RestConnection.CUSTOMER_ID_FOR_NAME + employeeId);
I am working on a RecyclerView which must be Draggable & swipeable. Everything works perfect.
The Data is getting Fetched in one class called ExerciseDataProvider & the RV code is another Fragment RecyclerListViewFragment.
The problem is that i can't notify Data changed from the FetchExercise on postExecute method. So the Data's are not getting populated in the RV.
Please Guide me in a Right Direction.
ACTIVITY
public class DraggableSwipeableExampleActivity extends AppCompatActivity {
private static final String FRAGMENT_TAG_DATA_PROVIDER = "data provider";
private static final String FRAGMENT_LIST_VIEW = "list view";
private static final String FRAGMENT_TAG_ITEM_PINNED_DIALOG = "item pinned dialog";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(new ExampleDataProviderFragment(), FRAGMENT_TAG_DATA_PROVIDER)
.commit();
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new RecyclerListViewFragment(), FRAGMENT_LIST_VIEW)
.commit();
}
}
public AbstractDataProvider getDataProvider() {
final Fragment fragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG_DATA_PROVIDER);
return ((ExampleDataProviderFragment) fragment).getDataProvider();
}
DATA PROVIDER
public class ExerciseDataProvider extends AbstractDataProvider {
private List<ConcreteData> mData;
private ConcreteData mLastRemovedData;
private int mLastRemovedPosition = -1;
public ExerciseDataProvider() {
new FetchExercise().execute();
mData = new LinkedList<>();
}
class FetchExercise extends AsyncTask<Void,Void,Void> {
#Override
protected Void doInBackground(Void... params) {
final int viewType = 0;
final int swipeReaction = RecyclerViewSwipeManager.REACTION_CAN_SWIPE_UP | RecyclerViewSwipeManager.REACTION_CAN_SWIPE_DOWN;
String url = "https://gist.githubusercontent.com/fake/cb9aa5494e7ee36ac3ca/raw/a4abfd19368063/exercise.JSON";
Log.d("Path", url);
try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
String jsonData = response.body().string();
try {
JSONArray jsonArray = new JSONArray(jsonData);
for (int i = 0; i < jsonArray.length(); i++) {
final long id = i;
JSONObject jsonObject = jsonArray.getJSONObject(i);
String exercise_name = jsonObject.getString("name");
int exercise_duration = jsonObject.getInt("duration");
mData.add(new ConcreteData(id, viewType, exercise_name, exercise_duration, swipeReaction));
Log.d("exercise_name", exercise_name);
}
} catch (JSONException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
}
#Override
public int getCount() {
return mData.size();
}
#Override
public Data getItem(int index) {
if (index < 0 || index >= getCount()) {
throw new IndexOutOfBoundsException("index = " + index);
}
return mData.get(index);
}
#Override
public int undoLastRemoval() {
if (mLastRemovedData != null) {
int insertedPosition;
if (mLastRemovedPosition >= 0 && mLastRemovedPosition < mData.size()) {
insertedPosition = mLastRemovedPosition;
} else {
insertedPosition = mData.size();
}
mData.add(insertedPosition, mLastRemovedData);
mLastRemovedData = null;
mLastRemovedPosition = -1;
return insertedPosition;
} else {
return -1;
}
}
#Override
public void moveItem(int fromPosition, int toPosition) {
if (fromPosition == toPosition) {
return;
}
final ConcreteData item = mData.remove(fromPosition);
mData.add(toPosition, item);
mLastRemovedPosition = -1;
}
#Override
public void removeItem(int position) {
//noinspection UnnecessaryLocalVariable
final ConcreteData removedItem = mData.remove(position);
mLastRemovedData = removedItem;
mLastRemovedPosition = position;
}
public static final class ConcreteData extends Data {
private final long mId;
private final String mText;
private final int mViewType;
private final int mDuration;
private boolean mPinned;
ConcreteData(long id, int viewType, String text, int duration, int swipeReaction) {
mId = id;
mViewType = viewType;
mText = text;
mDuration = duration;
}
#Override
public int getViewType() {
return mViewType;
}
#Override
public int getDuration() {
return mDuration;
}
#Override
public long getId() {
return mId;
}
#Override
public String toString() {
return mText;
}
#Override
public String getText() {
return mText;
}
#Override
public boolean isPinned() {
return mPinned;
}
#Override
public void setPinned(boolean pinned) {
mPinned = pinned;
}
}
}
RecyclerListViewFragment
public class RecyclerListViewFragment extends Fragment {
private RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private RecyclerView.Adapter mAdapter;
private RecyclerView.Adapter mWrappedAdapter;
private RecyclerViewDragDropManager mRecyclerViewDragDropManager;
private RecyclerViewSwipeManager mRecyclerViewSwipeManager;
private RecyclerViewTouchActionGuardManager mRecyclerViewTouchActionGuardManager;
public RecyclerListViewFragment() {
super();
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_recycler_list_view, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//noinspection ConstantConditions
mRecyclerView = (RecyclerView) getView().findViewById(R.id.recycler_view);
mLayoutManager = new LinearLayoutManager(getContext());
// touch guard manager (this class is required to suppress scrolling while swipe-dismiss animation is running)
mRecyclerViewTouchActionGuardManager = new RecyclerViewTouchActionGuardManager();
mRecyclerViewTouchActionGuardManager.setInterceptVerticalScrollingWhileAnimationRunning(true);
mRecyclerViewTouchActionGuardManager.setEnabled(true);
// drag & drop manager
mRecyclerViewDragDropManager = new RecyclerViewDragDropManager();
mRecyclerViewDragDropManager.setDraggingItemShadowDrawable(
(NinePatchDrawable) ContextCompat.getDrawable(getContext(), R.drawable.material_shadow_z3));
// swipe manager
mRecyclerViewSwipeManager = new RecyclerViewSwipeManager();
//adapter
final MyDraggableSwipeableItemAdapter myItemAdapter = new MyDraggableSwipeableItemAdapter(getDataProvider());
myItemAdapter.setEventListener(new MyDraggableSwipeableItemAdapter.EventListener() {
#Override
public void onItemRemoved(int position) {
((DraggableSwipeableExampleActivity) getActivity()).onItemRemoved(position);
}
#Override
public void onItemViewClicked(View v, boolean pinned) {
onItemViewClick(v, pinned);
}
});
mAdapter = myItemAdapter;
mWrappedAdapter = mRecyclerViewDragDropManager.createWrappedAdapter(myItemAdapter); // wrap for dragging
mWrappedAdapter = mRecyclerViewSwipeManager.createWrappedAdapter(mWrappedAdapter); // wrap for swiping
final GeneralItemAnimator animator = new SwipeDismissItemAnimator();
animator.setSupportsChangeAnimations(false);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mWrappedAdapter); // requires *wrapped* adapter
mRecyclerView.setItemAnimator(animator);
// additional decorations
//noinspection StatementWithEmptyBody
if (supportsViewElevation()) {
// Lollipop or later has native drop shadow feature. ItemShadowDecorator is not required.
} else {
mRecyclerView.addItemDecoration(new ItemShadowDecorator((NinePatchDrawable) ContextCompat.getDrawable(getContext(), R.drawable.material_shadow_z1)));
}
mRecyclerView.addItemDecoration(new SimpleListDividerDecorator(ContextCompat.getDrawable(getContext(), R.drawable.list_divider_h), true));
mRecyclerViewTouchActionGuardManager.attachRecyclerView(mRecyclerView);
mRecyclerViewSwipeManager.attachRecyclerView(mRecyclerView);
mRecyclerViewDragDropManager.attachRecyclerView(mRecyclerView);
}
#Override
public void onPause() {
mRecyclerViewDragDropManager.cancelDrag();
super.onPause();
}
#Override
public void onDestroyView() {
if (mRecyclerViewDragDropManager != null) {
mRecyclerViewDragDropManager.release();
mRecyclerViewDragDropManager = null;
}
if (mRecyclerViewSwipeManager != null) {
mRecyclerViewSwipeManager.release();
mRecyclerViewSwipeManager = null;
}
if (mRecyclerViewTouchActionGuardManager != null) {
mRecyclerViewTouchActionGuardManager.release();
mRecyclerViewTouchActionGuardManager = null;
}
if (mRecyclerView != null) {
mRecyclerView.setItemAnimator(null);
mRecyclerView.setAdapter(null);
mRecyclerView = null;
}
if (mWrappedAdapter != null) {
WrapperAdapterUtils.releaseAll(mWrappedAdapter);
mWrappedAdapter = null;
}
mAdapter = null;
mLayoutManager = null;
super.onDestroyView();
}
private void onItemViewClick(View v, boolean pinned) {
int position = mRecyclerView.getChildAdapterPosition(v);
if (position != RecyclerView.NO_POSITION) {
((DraggableSwipeableExampleActivity) getActivity()).onItemClicked(position);
}
}
public AbstractDataProvider getDataProvider() {
return ((DraggableSwipeableExampleActivity) getActivity()).getDataProvider();
}
public void notifyItemChanged(int position) {
mAdapter.notifyItemChanged(position);
}
public void notifyItemInserted(int position) {
mAdapter.notifyItemInserted(position);
mRecyclerView.scrollToPosition(position);
}
}
To update recyclerView from onPostExecute in a data provider class, your onPostExecute should have access to context where your recyclerView is defined.
Since your FetchExercise async task is defined inside ExerciseDataProvider class, try passing activity context to ExerciseDataProvider's constructor and then pass it on to FetchExercise async task as described here: getting context in AsyncTask
public class MyCustomTask extends AsyncTask<Void, Void, Long> {
private Context mContext;
public MyCustomTask (Context context){
mContext = context;
}
protected void onPostExecute(Long result) {
//use mContext to update recycler view
}
}
}
Use the context to update the recyclerView.
UPDATE
Step 1
Define an interface that will notify your activity of data set change inside a class that initialises your data provider class and pass activity context to constructor of data provider class.
public class ExampleDataProviderFragment extends Fragment {
private AbstractDataProvider mDataProvider;
//Define an interface that will notify your activity of data set change
public interface EventListener {
void onNotifyDataSetChanged();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
//Pass activity context to ExerciseDataProvider
mDataProvider = new ExerciseDataProvider(getActivity());
}
public AbstractDataProvider getDataProvider() {
return mDataProvider;
}
}
Step 2
Add context parameter to ExerciseDataProvider's constructor and use it to notify activity that implements your interface to notify dataset change.
public class ExerciseDataProvider extends AbstractDataProvider {
private List<ConcreteData> mData;
private ConcreteData mLastRemovedData;
private int mLastRemovedPosition = -1;
//Add context parameter to constructor
public ExerciseDataProvider(Context context) {
//Pass context to async task
new FetchExercise(context).execute();
mData = new LinkedList<>();
}
class FetchExercise extends AsyncTask<Void,Void,Integer> {
Context mContext;
public FetchExercise(Context context) {
mContext = context;
}
#Override
protected Integer doInBackground(Void... params) {
...
return 1;
}
#Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
//Typecast context to interface defined above
//and notify dataset changes by calling its method
ExampleDataProviderFragment.EventListener eventListener = (ExampleDataProviderFragment.EventListener)mContext;
eventListener.onNotifyDataSetChanged();
}
}
}
Step 3
Implement above defined interface in your activity class and notify recyclerview adapter inside it
public class DraggableSwipeableExampleActivity extends AppCompatActivity
implements ExampleDataProviderFragment.EventListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
...
}
//implement interface method and notify recyclerview of changes
#Override
public void onNotifyDataSetChanged() {
Fragment fragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_LIST_VIEW);
// you might need to change visibility of `mWrappedAdapter` in the fragment that defines it or create a getter for it so that you can access it here
((RecyclerListViewFragment) fragment).mWrappedAdapter.notifyDataSetChanged();
}
...
}
I think #random is correct you should be notifying your Recycle view on post execute.
#Override
protected void onPostExecute(Void aVoid) {
mRecyclerViewAdapter.notifyDataSetChanged();
super.onPostExecute(aVoid);
}
or if you have done something in your async task to add/delete something in the data set you would do:
#Override
protected void onPostExecute(Void aVoid) {
mRecyclerViewAdapter.notifyItemRemoved(itemposition); // or item added
mRecyclerViewAdapter.notifyDataSetChanged();
super.onPostExecute(aVoid);
}
Hope it helps !