I have a button in every cell of a RecyclerView that launches a download network call. The cell displays differently according to whether it's downloading, downloaded or finished.
my simplified code :
#Override public void onBindViewHolder(final CatalogViewHolder holder, int position) {
final DownloadStatusCallback statusCallback = new DownloadStatusCallback() {
#Override public void started() {
mainThreadHandler.post(new Runnable() {
#Override public void run() {
holder.itemView.setBackground(//color1
}
});
}
#Override public void finished() {
mainThreadHandler.post(new Runnable() {
#Override public void run() {
holder.itemView.setBackground(//color 2
}
});
}
#Override public void error(Exception e) {
mainThreadHandler.post(new Runnable() {
#Override public void run() {
holder.itemView.setBackground(//color 3
}
});
}
};
holder.button1.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View view) {
assyncCall(statusCallback);
}
});
}
The first time i clic on a cell, everything works fine. If I clic on the download button of another cell, both of them will update.
I understand that's due to recyclerview recycling cells, but I can't figure out how to do better.
Thanks !
my full adapter :
public class CatalogRecyclerAdapter extends RecyclerView.Adapter<CatalogViewHolder> {
public static final String TAG = "CatalogRecyclerAdapter";
private final LayoutInflater inflater;
private final DownloadCenter downloadCenter;
private final ListInterface.FlowController flowController;
private final ResourcesStringRepository resourcesStringRepository;
private final ImageManagerFactory imageManagerFactory;
private final Handler mainThreadHandler;
public CatalogRecyclerAdapter(LayoutInflater inflater, ListInterface.FlowController flowController,
DownloadCenter downloadCenter, ResourcesStringRepository resourcesStringRepository,
ImageManagerFactory imageManagerFactory, Handler mainThreadHandler) {
this.inflater = inflater;
this.flowController = flowController;
this.downloadCenter = downloadCenter;
this.resourcesStringRepository = resourcesStringRepository;
this.imageManagerFactory = imageManagerFactory;
this.mainThreadHandler = mainThreadHandler;
}
private static final int TITLE = 0;
private static final int USER = 2;
private static final int PROGRAM = 3;
private static final int COURSE = 4;
private static final int GROUP = 5;
private static final int MEDIA = 6;
private static final int ERROR = 7;
private static final int DEMO = 8;
//The list of all elements
private List<FilterableUser> users = new ArrayList<>();
private List<CatalogProgram> programs = new ArrayList<>();
private List<CatalogProgram> demos = new ArrayList<>();
private List<CatalogCourse> courses = new ArrayList<>();
private List<FilterableGroup> groups = new ArrayList<>();
private List<CatalogMedia> medias = new ArrayList<>();
//The list that will be displayed after filtering and research.
List<Object> displayedList = new ArrayList<>();
static final String TITLES[] = new String[10];
static {
Context ctx = M360Application.getContext();
TITLES[USER] = ctx.getString(R.string.users);
TITLES[PROGRAM] = ctx.getString(R.string.programs);
TITLES[COURSE] = ctx.getString(R.string.courses);
TITLES[GROUP] = ctx.getString(R.string.groups);
TITLES[MEDIA] = ctx.getString(R.string.documents);
TITLES[DEMO] = ctx.getString(R.string.programs_demo);
}
private String searchString;
#Override public int getItemViewType(int position) {
if (displayedList.get(position) instanceof String) {
return TITLE;
} else if (displayedList.get(position) instanceof FilterableUser) {
return USER;
} else if (displayedList.get(position) instanceof CatalogProgramDemo) {
return DEMO;
} else if (displayedList.get(position) instanceof CatalogProgram) {
return PROGRAM;
} else if (displayedList.get(position) instanceof CatalogCourse) {
return COURSE;
} else if (displayedList.get(position) instanceof FilterableGroup) {
return GROUP;
} else if (displayedList.get(position) instanceof CatalogMedia) {
return MEDIA;
} else if (displayedList.get(position) instanceof CatalogError) {
return ERROR;
} else {
throw new ClassCastException(
"this adapter's displayedList is corrupted" + displayedList.get(position).toString());
}
}
public void setData(List<Filterable> data, String searchedString) {
searchString = searchedString;
setData(data);
}
private void setData(List<Filterable> data) {
LogDev.i(TAG, "setting data size: " + data.size());
groups.clear();
users.clear();
programs.clear();
demos.clear();
courses.clear();
medias.clear();
for (Filterable element : data) {
if (element instanceof CatalogCourse) {
courses.add((CatalogCourse) element);
} else if (element instanceof FilterableUser) {
users.add((FilterableUser) element);
} else if (element instanceof CatalogProgramDemo) {
demos.add((CatalogProgramDemo) element);
} else if (element instanceof CatalogProgram) {
programs.add((CatalogProgram) element);
} else if (element instanceof FilterableGroup) {
groups.add((FilterableGroup) element);
} else if (element instanceof CatalogMedia) {
medias.add((CatalogMedia) element);
}
}
constructDataSet();
}
private void constructDataSet() {
displayedList.clear();
if (!demos.isEmpty()) {
displayedList.add(TITLES[DEMO]);
displayedList.addAll(demos);
}
if (!programs.isEmpty()) {
displayedList.add(TITLES[PROGRAM]);
displayedList.addAll(programs);
}
if (!courses.isEmpty()) {
displayedList.add(TITLES[COURSE]);
displayedList.addAll(courses);
}
if (!users.isEmpty()) {
displayedList.add(TITLES[USER]);
displayedList.addAll(users);
}
if (!groups.isEmpty()) {
displayedList.add(TITLES[GROUP]);
displayedList.addAll(groups);
}
if (!medias.isEmpty()) {
displayedList.add(TITLES[MEDIA]);
displayedList.addAll(medias);
}
if (displayedList.isEmpty()) {
displayedList.add(new CatalogError());
}
LogDev.w(TAG, "displayedList.size() : " + displayedList.size());
notifyDataSetChanged();
}
#Override public CatalogViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case TITLE:
return new TitleViewHolder(inflater.inflate(R.layout.item_list_title_catalog, parent, false));
case USER:
return new UserViewHolder(inflater.inflate(R.layout.widget_user_small, parent, false));
case PROGRAM:
case DEMO:
return new ProgramViewHolder(inflater.inflate(R.layout.widget_program_small, parent, false));
case COURSE:
return new CourseViewHolder(inflater.inflate(R.layout.widget_course_small, parent, false));
case GROUP:
return new GroupViewHolder(inflater.inflate(R.layout.widget_group_small, parent, false));
case MEDIA:
return new MediaViewHolder(inflater.inflate(R.layout.widget_media_small, parent, false));
case ERROR:
return new CatalogErrorViewHolder(inflater.inflate(R.layout.widget_noresult_small, parent, false));
default:
LogDev.e(TAG, "view type not supported");
return null;
}
}
#Override public void onBindViewHolder(CatalogViewHolder holder, int position) {
Object displayedObject = displayedList.get(position);
//holder.bind(displayedObject, errorDisplayInterface);
if (holder instanceof TitleViewHolder && displayedObject instanceof String) {
((TitleViewHolder) holder).tv.setText((String) displayedObject);
} else if (holder instanceof ProgramViewHolder && displayedObject instanceof CatalogProgram) {
bindProgramViewHolder((ProgramViewHolder) holder, (CatalogProgram) displayedObject);
} else if (holder instanceof CourseViewHolder && displayedObject instanceof CatalogCourse) {
bindCourseViewHolder((CourseViewHolder) holder, (CatalogCourse) displayedObject);
} else if (holder instanceof GroupViewHolder && displayedObject instanceof FilterableGroup) {
bindGroupViewHolder((GroupViewHolder) holder, (FilterableGroup) displayedObject);
} else if (holder instanceof UserViewHolder && displayedObject instanceof FilterableUser) {
bindUserViewHolder((UserViewHolder) holder, (FilterableUser) displayedObject);
} else if (holder instanceof MediaViewHolder && displayedObject instanceof CatalogMedia) {
bindMediaViewHolder((MediaViewHolder) holder, (CatalogMedia) displayedObject);
} else if (holder instanceof CatalogErrorViewHolder) {
//No binding with any data
} else {
throw new ClassCastException(displayedObject.toString());
}
//Highlight
if (searchString != null && !searchString.isEmpty())
{
TextViewHighlighter.highlight(holder, searchString);
}
}
private void bindCourseViewHolder(final CourseViewHolder courseViewHolder, final CatalogCourse course) {
courseViewHolder.name_textView.setText(course.name);
courseViewHolder.viewNb_textView.setText(course.views != null ? course.views.toString() : "0");
if (course.elementCount == null) {
courseViewHolder.counterLinear.setVisibility(View.GONE);
} else {
courseViewHolder.counterLinear.setVisibility(View.VISIBLE);
courseViewHolder.questionNb_textView.setText(
course.elementCount.questions != null ? course.elementCount.questions.toString() : "0");
courseViewHolder.mediaNb_textView.setText(
course.elementCount.medias != null ? course.elementCount.medias.toString() : "0");
courseViewHolder.sheetNb_textView.setText(
course.elementCount.sheets != null ? course.elementCount.sheets.toString() : "0");
}
imageManagerFactory.course(course.id).thumbnail(courseViewHolder.pic_imageView);
//new CourseImageManager(course.id).load(courseViewHolder.pic_imageView);
View.OnClickListener clickListener = new View.OnClickListener() {
#Override public void onClick(View view) {
flowController.routeToCourse(course.id);
}
};
courseViewHolder.container.setOnClickListener(clickListener);
if (course.canBeOffline) {
courseViewHolder.downloadBlock.setVisibility(View.VISIBLE);
DownloadState state = downloadCenter.getCourseStatus(course.id);
LogDev.i(TAG, "can be offline " + state.name());
if (state == DownloadState.DOWNLOADING) {
updateDownloadBlock(courseViewHolder, DownloadableStatus.DOWNLOADING);
}
if (state == DownloadState.TO_DOWNLOAD) {
updateDownloadBlock(courseViewHolder, DownloadableStatus.DOWNLOADABLE);
}
if (state == DownloadState.DOWNLOADED || state == DownloadState.DOWNLOADED_WITH_SHARED_MODE) {
updateDownloadBlock(courseViewHolder, DownloadableStatus.DOWNLOADED);
} else {
DownloadStatusCallback statusCallback = new DownloadStatusCallback() {
#Override public void started() {
LogDev.i(TAG, "started");
mainThreadHandler.post(new Runnable() {
#Override public void run() {
updateDownloadBlock(courseViewHolder, DownloadableStatus.DOWNLOADING);
}
});
}
#Override public void finished() {
mainThreadHandler.post(new Runnable() {
#Override public void run() {
updateDownloadBlock(courseViewHolder, DownloadableStatus.DOWNLOADED);
}
});
}
#Override public void error(Exception e) {
mainThreadHandler.post(new Runnable() {
#Override public void run() {
updateDownloadBlock(courseViewHolder, DownloadableStatus.ERROR);
}
});
}
};
downloadCenter.subscribe(course.id, statusCallback);
courseViewHolder.downloadBlock.setOnClickListener(new View.OnClickListener()
{
#Override public void onClick(View v) {
new Thread() {
#Override public void run() {
super.run();
try {
downloadCenter.downloadCourse(course.id, null);
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
});
}
} else {
LogDev.i(TAG, "can't be offline");
courseViewHolder.downloadBlock.setVisibility(View.INVISIBLE);
}
}
private void updateDownloadBlock(CourseViewHolder courseViewHolder, DownloadableStatus status) {
if (status == null) return;
courseViewHolder.downloadBlock.setVisibility(
status.equals(DownloadableStatus.NOT_DOWNLOADABLE) ? View.GONE : View.VISIBLE);
courseViewHolder.downloadImage.setVisibility(
status.equals(DownloadableStatus.DOWNLOADABLE) ? View.VISIBLE : View.GONE);
courseViewHolder.downloadProgress.setVisibility(
status.equals(DownloadableStatus.DOWNLOADING) ? View.VISIBLE : View.GONE);
courseViewHolder.downloadedImage.setVisibility(
status.equals(DownloadableStatus.DOWNLOADED) ? View.VISIBLE : View.GONE);
courseViewHolder.downloadErrImage.setVisibility(
status.equals(DownloadableStatus.ERROR) ? View.VISIBLE : View.GONE);
}
private enum DownloadableStatus {
NOT_DOWNLOADABLE, DOWNLOADABLE, DOWNLOADING, DOWNLOADED, ERROR
}
private void bindProgramViewHolder(ProgramViewHolder programViewHolder, final CatalogProgram program) {
imageManagerFactory.program(program.id).thumbnail(programViewHolder.pic_imageView);
//new ProgramImageManager(program.id).load(programViewHolder.pic_imageView);
View.OnClickListener onClickListener = new View.OnClickListener() {
#Override public void onClick(View view) {
flowController.routeToProgram(program.id);
}
};
programViewHolder.container.setOnClickListener(onClickListener);
programViewHolder.pic_imageView.setOnClickListener(onClickListener);
programViewHolder.title_textView.setText(program.name);
programViewHolder.viewCount_textView.setText(program.views != null ? program.views.toString() : "0");
}
private void bindUserViewHolder(UserViewHolder userViewHolder, final FilterableUser user) {
userViewHolder.name_textView.setText(user.name);
userViewHolder.job_textView.setText(user.description);
imageManagerFactory.user(user.id).thumbnail(userViewHolder.pic_imageView);
//new UserImageManager(user.id).loadProfilePic(userViewHolder.pic_imageView, NetworkUtils.isNetworkAvailable(),
// true);
View.OnClickListener onClickListener = new View.OnClickListener() {
#Override public void onClick(View view) {
flowController.routeToUser(user.id);
}
};
userViewHolder.pic_imageView.setOnClickListener(onClickListener);
userViewHolder.container.setOnClickListener(onClickListener);
}
private void bindMediaViewHolder(MediaViewHolder mediaViewHolder, final CatalogMedia media) {
imageManagerFactory.media(media.id, media.type, media.extention).symbolOnThumbnail(mediaViewHolder.complex);
//new MediaImageManager(media).load(mediaViewHolder.pic_imageView, NetworkUtils.isNetworkAvailable(), false);
mediaViewHolder.title_textView.setText(media.title);
mediaViewHolder.authorName_textView.setText(media.authorName);
View.OnClickListener onClickListener = new View.OnClickListener() {
#Override public void onClick(final View view) {
flowController.routeToDocument(media.id);
}
};
mediaViewHolder.complex.setOnClickListener(onClickListener);
mediaViewHolder.container.setOnClickListener(onClickListener);
}
private void bindGroupViewHolder(GroupViewHolder groupViewHolder, final FilterableGroup group) {
View.OnClickListener onClickListener = new View.OnClickListener() {
#Override public void onClick(View view) {
flowController.routeToGrouop(group.id);
}
};
groupViewHolder.pic_imageView.setOnClickListener(onClickListener);
groupViewHolder.container.setOnClickListener(onClickListener);
groupViewHolder.name_textView.setText(group.name);
String str = resourcesStringRepository.getQuantityString(R.plurals.catalog_group_stat_program,
group.nbProgramsRunning, group.nbProgramsRunning);
str += " - " + resourcesStringRepository.getQuantityString(R.plurals.catalog_group_stat_user, group.nbUser,
group.nbUser);
groupViewHolder.stats_textView.setText(str);
imageManagerFactory.group(group.id).thumbnail(groupViewHolder.pic_imageView);
//new GroupImageManager(group.id).load(groupViewHolder.pic_imageView, NetworkUtils.isNetworkAvailable(), true);
}
#Override public int getItemCount() {
return displayedList.size();
}
}
It is recycling the views.So while clicking the button you have to store its position and change views accordingly.
Maintain a position storing variable globally like this
private int itemClicked=-1;
While clicking the view store the position into itemclicked
holder.button1.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View view) {
itemclicked=position;
assyncCall(statusCallback);
}
});
Then while updating views check if the position is same like this
if(position==itemclicked){
//show download for clicked view
}else{
//show download stopped for other views
}
Solution
As Surender and Trickcy Solution suggested, I updated the presented data and then tell the adapter to update the cell accordingly :
DownloadStatusCallback statusCallback = new DownloadStatusCallback() {
#Override public void started() {
LogDev.i(TAG, "started");
course.downloadState = DownloadState.DOWNLOADING;
final int position = courseViewHolder.getAdapterPosition();
mainThreadHandler.post(new Runnable() {
#Override public void run() {
notifyItemChanged(position);
}
});
}
#Override public void finished() {
course.downloadState = DownloadState.DOWNLOADED;
final int position = courseViewHolder.getAdapterPosition();
mainThreadHandler.post(new Runnable() {
#Override public void run() {
notifyItemChanged(position);
}
});
}
#Override public void error(Exception e) {
course.downloadState = DownloadState.ERROR_WHILE_DOWNLOADING;
final int position = courseViewHolder.getAdapterPosition();
mainThreadHandler.post(new Runnable() {
#Override public void run() {
notifyItemChanged(position);
}
});
}
};
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.
I am building pager Recyclerview where each page has a timer. After some seconds i need to change the page based on timer value. But the issue is that whenever I switch to other page the previous timer starts again. I did everything, i created timer in onCreateViewHolder, I created timer in onBindViewHolder like everyone said but nothing worked.
Kindly help me out in this. Below is my code.
public class GamePlayAdapter extends RecyclerView.Adapter<BaseViewHolder> {
private List<Question> questionList;
private GamePlayHelper gamePlayHelper;
private static final int ITEM_TYPE1 = 1;
private static final int ITEM_TYPE2 = 2;
private Context context;
GamePlayAdapter(List<Question> questionList, GamePlayHelper gamePlayHelper, Context context) {
this.questionList = questionList;
this.gamePlayHelper = gamePlayHelper;
this.context = context;
}
#Override
public int getItemViewType(int position) {
if (questionList.get(position).getMediaExt().equals("")) {
return ITEM_TYPE1;
} else {
return ITEM_TYPE2;
}
}
#NotNull
#Override
public BaseViewHolder onCreateViewHolder(#NotNull ViewGroup parent, int viewType) {
if (viewType == ITEM_TYPE1) {
GamePlayItem1Binding gamePlayItemBinding = GamePlayItem1Binding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new GamePlayItem1VH(gamePlayItemBinding);
} else {
GamePlayItem2Binding gamePlayItem2Binding = GamePlayItem2Binding.inflate(LayoutInflater.from(parent.getContext()), parent, false);
GamePlayItem2VH gamePlayItem2VH = new GamePlayItem2VH(gamePlayItem2Binding);
createTimer(gamePlayItem2VH);
return gamePlayItem2VH;
}
}
private void createTimer(BaseViewHolder viewHolder) {
if (viewHolder instanceof GamePlayItem1VH) {
if (((GamePlayItem1VH) viewHolder).countDownTimerUtils != null)
((GamePlayItem1VH) viewHolder).countDownTimerUtils.cancel();
((GamePlayItem1VH) viewHolder).countDownTimerUtils = new CountDownTimerUtils(10000, 1000, CountDownTimerUtils.TIMER_TYPE.SECONDS) {
#Override
public void onTimerTick(String timerValue) {
Timber.d(timerValue);
((GamePlayItem1VH) viewHolder).updateTimeValue(timerValue);
}
#Override
public void onTimerFinish() {
Timber.d("Finish");
((GamePlayItem1VH) viewHolder).updateScreen();
((GamePlayItem1VH) viewHolder).countDownTimerUtils.cancel();
}
};
((GamePlayItem1VH) viewHolder).countDownTimerUtils.start();
} else if (viewHolder instanceof GamePlayItem2VH) {
/* if (((GamePlayItem2VH) viewHolder).countDownTimerUtils != null)
((GamePlayItem2VH) viewHolder).countDownTimerUtils.cancel();*/
((GamePlayItem2VH) viewHolder).countDownTimerUtils = new CountDownTimerUtils(10000, 1000, CountDownTimerUtils.TIMER_TYPE.SECONDS) {
#Override
public void onTimerTick(String timerValue) {
// Timber.d(timerValue);
Log.d("GamePlay", timerValue);
((GamePlayItem2VH) viewHolder).updateTimeValue(timerValue);
}
#Override
public void onTimerFinish() {
//Timber.d("Finish");
Log.d("GamePlay", "Finish");
((GamePlayItem2VH) viewHolder).updateScreen();
// ((GamePlayItem2VH) viewHolder).countDownTimerUtils.cancel();
}
};
((GamePlayItem2VH) viewHolder).countDownTimerUtils.start();
}
}
#Override
public void onBindViewHolder(#NonNull BaseViewHolder holder, int position) {
holder.onBind(position);
}
#Override
public int getItemCount() {
return questionList.size();
}
class GamePlayItem1VH extends BaseViewHolder {
private GamePlayItem1Binding binding;
private int currentPosition = 0;
private CountDownTimerUtils countDownTimerUtils;
GamePlayItem1VH(GamePlayItem1Binding binding) {
super(binding.getRoot());
this.binding = binding;
GamePlayItem1ViewModel gamePlayItem1ViewModel = new GamePlayItem1ViewModel();
binding.setViewModel(gamePlayItem1ViewModel);
binding.executePendingBindings();
binding.gameplayItem1QuestionProgress.setMax(questionList.size());
}
#Override
public void onBind(int position) {
currentPosition = position;
startTimer();
updateProgress(position);
binding.gameplayItem1NoOfQues.setText(String.format("%s/%s", position + 1, questionList.size()));
binding.gameplayItem1QuestionTitle.setText(questionList.get(position).getQuestionText());
binding.gameplayItemOptionBtn1.setText(questionList.get(position).getOptions().get(0).getOptionText());
binding.gameplayItemOptionBtn2.setText(questionList.get(position).getOptions().get(1).getOptionText());
binding.gameplayItemOptionBtn1.setOnClickListener(v ->
{
binding.gameplayItemOptionBtn1.setTextColor(context.getResources().getColor(R.color.white));
binding.gameplayItemOptionBtn1.setBackgroundResource(R.drawable.button_question_selected_correct);
onItemClick(position);
});
binding.gameplayItemOptionBtn2.setOnClickListener(v ->
{
binding.gameplayItemOptionBtn2.setTextColor(context.getResources().getColor(R.color.white));
binding.gameplayItemOptionBtn2.setBackgroundResource(R.drawable.button_question_selected_wrong);
onItemClick(position);
});
binding.gameplayItemOptionBtn3.setOnClickListener(v ->
{
binding.gameplayItemOptionBtn3.setTextColor(context.getResources().getColor(R.color.white));
binding.gameplayItemOptionBtn3.setBackgroundResource(R.drawable.button_question_selected_correct);
onItemClick(position);
});
binding.gameplayItemOptionBtn4.setOnClickListener(v ->
{
binding.gameplayItemOptionBtn4.setTextColor(context.getResources().getColor(R.color.white));
binding.gameplayItemOptionBtn4.setBackgroundResource(R.drawable.button_question_selected_wrong);
onItemClick(position);
});
}
private void startTimer() {
countDownTimerUtils = new CountDownTimerUtils(10000, 1000, CountDownTimerUtils.TIMER_TYPE.SECONDS) {
#Override
public void onTimerFinish() {
updateScreen();
cancel();
}
#Override
public void onTimerTick(String timerValue) {
updateTimeValue(timerValue);
}
};
countDownTimerUtils.start();
}
private void updateProgress(int position) {
binding.gameplayItem1QuestionProgress.setProgress(position + 1);
}
private void updateTimeValue(String timerValue) {
binding.gameplayItem1TimerTxt.setText(timerValue);
}
private void updateScreen() {
countDownTimerUtils.cancel();
onItemClick(currentPosition);
}
void onItemClick(int pagePosition) {
new Handler().postDelayed(() ->
gamePlayHelper.onQuestionItemSelected(pagePosition + 1), 500);
}
}
class GamePlayItem2VH extends BaseViewHolder {
GamePlayItem2Binding binding;
GamePlayItem2ViewModel gamePlayItem2ViewModel;
private int currentPosition = 0;
private CountDownTimerUtils countDownTimerUtils;
GamePlayItem2VH(GamePlayItem2Binding binding) {
super(binding.getRoot());
this.binding = binding;
gamePlayItem2ViewModel = new GamePlayItem2ViewModel();
binding.setViewModel(gamePlayItem2ViewModel);
binding.executePendingBindings();
binding.gameplayItem2QuestionProgress.setMax(questionList.size());
}
#Override
public void onBind(int position) {
// startTimer();
updateProgress(position);
currentPosition = position;
binding.gameplayItem2NoOfQues.setText(String.format("%s/%s", position + 1, questionList.size()));
binding.gameplayItem2QuestionTitle.setText(questionList.get(position).getQuestionText());
binding.gameplayItem2OptionBtn1.setText(questionList.get(position).getOptions().get(0).getOptionText());
binding.gameplayItem2OptionBtn2.setText(questionList.get(position).getOptions().get(1).getOptionText());
BindingUtils.setImageUrl(binding.gameplayItem2QuestionImg, questionList.get(position).getMediaURL());
binding.gameplayItem2OptionBtn1.setOnClickListener(v ->
{
binding.gameplayItem2OptionBtn1.setTextColor(context.getResources().getColor(R.color.white));
binding.gameplayItem2OptionBtn1.setBackgroundResource(R.drawable.button_question_selected_correct);
onItemClick(position);
});
binding.gameplayItem2OptionBtn2.setOnClickListener(v ->
{
binding.gameplayItem2OptionBtn2.setTextColor(context.getResources().getColor(R.color.white));
binding.gameplayItem2OptionBtn2.setBackgroundResource(R.drawable.button_question_selected_wrong);
onItemClick(position);
});
binding.gameplayItem2OptionBtn3.setOnClickListener(v ->
{
binding.gameplayItem2OptionBtn3.setTextColor(context.getResources().getColor(R.color.white));
binding.gameplayItem2OptionBtn3.setBackgroundResource(R.drawable.button_question_selected_correct);
onItemClick(position);
});
binding.gameplayItem2OptionBtn4.setOnClickListener(v ->
{
binding.gameplayItem2OptionBtn4.setTextColor(context.getResources().getColor(R.color.white));
binding.gameplayItem2OptionBtn4.setBackgroundResource(R.drawable.button_question_selected_wrong);
onItemClick(position);
});
}
private void startTimer() {
countDownTimerUtils = new CountDownTimerUtils(10000, 1000, CountDownTimerUtils.TIMER_TYPE.SECONDS) {
#Override
public void onTimerFinish() {
updateScreen();
cancel();
Log.d("GamePlay", "finish");
}
#Override
public void onTimerTick(String timerValue) {
updateTimeValue(timerValue);
Log.d("GamePlay", timerValue);
}
};
countDownTimerUtils.start();
}
private void updateProgress(int position) {
binding.gameplayItem2QuestionProgress.setProgress(position + 1);
}
private void updateScreen() {
// countDownTimerUtils.cancel();
// countDownTimerUtils = null;
gamePlayHelper.onQuestionItemSelected(currentPosition + 1);
}
private void updateTimeValue(String timerValue) {
binding.gameplayItem2TimerTxt.setText(timerValue);
}
void onItemClick(int pagePosition) {
// countDownTimerUtils.cancel();
// countDownTimerUtils = null;
new Handler().postDelayed(() ->
gamePlayHelper.onQuestionItemSelected(pagePosition + 1), 500);
}
}
void updateDataSet(int position) {
notifyDataSetChanged();
}
}
I am currently working on an app, that finds all MP3s on a users phone and then puts them into a list. This works very fine and is very quick, even with many songs. Now I populate a new list with an object for each item of the list to then display it inside my recyclerview. The problem is, that I have 700+ songs on my phone and this blocks the UI thread quite some time.
Now, I want to use the recyclerview to not load all items from the list into the objects all at once but rather only when they are about to be displayed - but I have NO clue over how to do this. Right now, all objects are build and then displayed in a very long scrollview from the recyclerview after the UI thread has been blocked for a good 30 seconds. Can please anyone help me? Here is my code:
namespace Media_Player
{
[Activity(Label = "Media_Player", MainLauncher = true)]
public class MainActivity : Activity
{
static public MediaPlayer mediaPlayer;
List<MP3object> mp3;
MediaMetadataRetriever reader;
public static Button btn_StartOrPause, btn_Stop;
public static TextView txt_CurrentSong;
public static bool stopIsActive = false, firstStart = true;
public static Android.Net.Uri CurrentActiveSongUri;
RecyclerView mRecyclerView;
RecyclerView.LayoutManager mLayoutManager;
PhotoAlbumAdapter mAdapter;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.test);
reader = new MediaMetadataRetriever();
PopulateMP3List(ReturnPlayableMp3(true));
mediaPlayer = new MediaPlayer();
InitRecView();
}
private void InitRecView()
{
// Instantiate the adapter and pass in its data source:
mAdapter = new PhotoAlbumAdapter(mp3);
// Get our RecyclerView layout:
mRecyclerView = FindViewById<RecyclerView>(Resource.Id.recyclerView);
// Plug the adapter into the RecyclerView:
mRecyclerView.SetAdapter(mAdapter);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.SetLayoutManager(mLayoutManager);
}
private void PopulateMP3List(List<string> content)
{
mp3 = new List<MP3object>();
foreach (string obj in content)
{
WriteMetaDataToFileList(obj);
}
}
void WriteMetaDataToFileList(string obj)
{
reader.SetDataSource(obj);
//Write Mp3 as object to global list
MP3object ob = new MP3object();
{
if(reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle) != null)
{
ob.SongName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyTitle);
}
else
{
ob.SongName = Resources.GetString(Resource.String.Unknown);
}
if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyArtist) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyArtist) != null)
{
ob.ArtistName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyArtist);
}
else
{
ob.ArtistName = Resources.GetString(Resource.String.Unknown);
}
if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyAlbum) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyAlbum) != null)
{
ob.AlbumName = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyAlbum);
}
else
{
ob.AlbumName = Resources.GetString(Resource.String.Unknown);
}
if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != null)
{
ob.Year = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear);
}
else
{
ob.Year = Resources.GetString(Resource.String.Unknown);
}
if (reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != "" && reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear) != null)
{
ob.Year = reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyYear);
}
else
{
ob.Year = Resources.GetString(Resource.String.Unknown);
}
ob.Mp3Uri = obj; // can never be unknown!
ob.DurationInSec = int.Parse(reader.ExtractMetadata(MediaMetadataRetriever.MetadataKeyDuration)) / 1000; // can never be unknown, div by 1000 to get sec not millis
}
mp3.Add(ob);
}
public List<string> ReturnPlayableMp3(bool sdCard)
{
List<string> res = new List<string>();
string phyle;
string path1 = null;
if(sdCard) // get mp3 from SD card
{
string baseFolderPath = "";
try
{
bool getSDPath = true;
Context context = Application.Context;
Java.IO.File[] dirs = context.GetExternalFilesDirs(null);
foreach (Java.IO.File folder in dirs)
{
bool IsRemovable = Android.OS.Environment.InvokeIsExternalStorageRemovable(folder);
bool IsEmulated = Android.OS.Environment.InvokeIsExternalStorageEmulated(folder);
if (getSDPath ? IsRemovable && !IsEmulated : !IsRemovable && IsEmulated)
baseFolderPath = folder.Path;
}
}
catch (Exception ex)
{
Console.WriteLine("GetBaseFolderPath caused the following exception: {0}", ex);
}
string xy = baseFolderPath.Remove(18); // This is result after this, but this hard coded solution could be a problem on different phones.: "/storage/05B6-2226/Android/data/Media_Player.Media_Player/files"
path1 = xy;
// path to SD card and MUSIC "/storage/05B6-2226/"
}
else // get Mp3 from internal storage
{
path1 = Android.OS.Environment.ExternalStorageDirectory.ToString();
}
var mp3Files = Directory.EnumerateFiles(path1, "*.mp3", SearchOption.AllDirectories);
foreach (string currentFile in mp3Files)
{
phyle = currentFile;
res.Add(phyle);
}
return res;
}
}
public class PhotoViewHolder : RecyclerView.ViewHolder
{
public ImageView Image { get; private set; }
public TextView Caption { get; private set; }
public PhotoViewHolder(View itemView) : base(itemView)
{
// Locate and cache view references:
Image = itemView.FindViewById<ImageView>(Resource.Id.imageView);
Caption = itemView.FindViewById<TextView>(Resource.Id.textView);
}
}
public class PhotoAlbumAdapter : RecyclerView.Adapter
{
public List<MP3object> mp3;
public PhotoAlbumAdapter(List<MP3object> mp3)
{
this.mp3 = mp3;
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.From(parent.Context).
Inflate(Resource.Layout.lay, parent, false);
PhotoViewHolder vh = new PhotoViewHolder(itemView);
return vh;
}
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
{
PhotoViewHolder vh = holder as PhotoViewHolder;
vh.Caption.Text = mp3[position].SongName;
}
public override int ItemCount
{
get { return mp3.Count(); }
}
}
}
So getting the list of strings with the locations of the Mp3 works very quickly, but then "WriteMetaDataToFileList(obj)" kicks in, comming from "PopulateMP3List(List content)" and this is what takes so long. What I think I need is for the recyclerview to only build the first 20 objects, and when the user starts scrolling, builds the next 20 objects and attaches them to list for them to also be scrolled. Please help me out here :)
Here is an abstract class:
public abstract class PaginationScrollListener extends RecyclerView.OnScrollListener {
private LinearLayoutManager linearLayoutManager;
protected PaginationScrollListener(LinearLayoutManager linearLayoutManager) {
this.linearLayoutManager = linearLayoutManager;
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = linearLayoutManager.getChildCount();
int totalItemCount = linearLayoutManager.getItemCount();
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
if (!isLoading() && !isLastPage()) {
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0) {
loadMoreItems();
}
}
}
protected abstract void loadMoreItems();
public abstract boolean isLastPage();
public abstract boolean isLoading();
}
and In your adapter you must follow this pattern:
public class ConsultancyAdapter extends RecyclerView.Adapter<ConsultancyAdapter.ConsultancyVH> {
private static final int ITEM = 0;
private static final int LOADING = 1;
private boolean isLoadingAdded = false;
public ConsultancyAdapter(List<Consultancy> consultancies, ConsultancyAdapterListener listener) {
}
#NonNull
#Override
public ConsultancyVH onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
switch (viewType) {
case ITEM:
viewHolder = getViewHolder(parent, layoutInflater);
break;
case LOADING:
View v2 = layoutInflater.inflate(R.layout.item_progress, parent, false);
viewHolder = new ConsultancyVH(v2);
break;
}
return (ConsultancyVH) viewHolder;
}
#NonNull
private RecyclerView.ViewHolder getViewHolder(ViewGroup parent, LayoutInflater inflater) {
RecyclerView.ViewHolder viewHolder;
View v1 = inflater.inflate(R.layout.item_consultancy, parent, false);
viewHolder = new ConsultancyVH(v1);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull ConsultancyVH holder, int position) {
Consultancy consultancy = consultancies.get(position);
switch (getItemViewType(position)) {
case ITEM:
ConsultancyVH mySingeCounseller = holder;
holder.title.setText(consultancy.getTitle()); // set cardTitle
holder.fieldArea.setText(consultancy.getField_filedoctorskills());
break;
case LOADING:
break;
}
}
#Override
public int getItemCount() {
return consultancies.size();
}
#Override
public int getItemViewType(int position) {
return (position == consultancies.size() - 1 && isLoadingAdded) ? LOADING : ITEM;
}
public void add(Consultancy mc) {
consultancies.add(mc);
notifyItemInserted(consultancies.size() - 1);
}
public void addAll(List<Consultancy> mcList) {
for (Consultancy mc : mcList) {
add(mc);
}
}
public void remove(Consultancy city) {
int position = consultancies.indexOf(city);
if (position > -1) {
consultancies.remove(position);
notifyItemRemoved(position);
}
}
public Consultancy getItem(int position) {
return consultancies.get(position);
}
public void clear() {
isLoadingAdded = false;
while (getItemCount() > 0) {
remove(getItem(0));
}
}
public boolean isEmpty() {
return getItemCount() == 0;
}
public void addLoadingFooter() {
isLoadingAdded = true;
add(new Consultancy());
}
public void removeLoadingFooter() {
isLoadingAdded = false;
int position = consultancies.size() - 1;
Consultancy item = getItem(position);
if (item != null) {
consultancies.remove(position);
notifyItemRemoved(position);
}
}
public interface ConsultancyAdapterListener {
void onCaseClicked(int position, String nid, String fieldArea, String title);
}
protected class ConsultancyVH extends RecyclerView.ViewHolder {
private TextView title, fieldArea;
private CircleImageView iconProfile;
private MaterialRippleLayout caseButtonRipple;
public ConsultancyVH(View itemView) {
super(itemView);
caseButtonRipple = itemView.findViewById(R.id.case_button_ripple);
this.title = itemView.findViewById(R.id.docName);
this.fieldArea = itemView.findViewById(R.id.fieldArea);
this.iconProfile = itemView.findViewById(R.id.icon_profile);
}
}
}
and in your activity:
private void setScrollListener() {
recyclerView.addOnScrollListener(new PaginationScrollListener(linearLayoutManager) {
#Override
protected void loadMoreItems() {
isLoading = true;
currentPage += 1;
loadNextPage();
}
#Override
public boolean isLastPage() {
return isLastPage;
}
#Override
public boolean isLoading() {
return isLoading;
}
});
loadFirstPage();
}
and in my loadFirstPage i talk to a API and you need some your code:
private void loadFirstPage() {
CallData().enqueue(new DefaultRetrofitCallback<List<Consultancy>>() {
#Override
protected void onFailure(Throwable t) {
super.onFailure(t);
}
#Override
protected void onSuccess(List<Consultancy> response) {
swipeRefreshLayout.setRefreshing(false);
dataList = response;
adapter.addAll(dataList);
recyclerView.setAdapter(adapter);
if (!checkLast(response)) adapter.addLoadingFooter();
else isLastPage = true;
}
#Override
protected void onOtherStatus(Response<List<Consultancy>> response) {
super.onOtherStatus(response);
}
#Override
protected void always() {
super.always();
}
});
}
and loadNextPage:
private void loadNextPage() {
CallData().enqueue(new DefaultRetrofitCallback<List<Consultancy>>() {
#Override
protected void onFailure(Throwable t) {
super.onFailure(t);
}
#Override
protected void onSuccess(List<Consultancy> response) {
swipeRefreshLayout.setRefreshing(false);
adapter.removeLoadingFooter();
isLoading = false;
swipeRefreshLayout.setRefreshing(false);
adapter.addAll(response);
if (!checkLast(response)) adapter.addLoadingFooter();
else isLastPage = true;
}
#Override
protected void onOtherStatus(Response<List<Consultancy>> response) {
super.onOtherStatus(response);
}
#Override
protected void always() {
super.always();
}
});
}
I am developing one quiz android application in which questions and their respective options and answer will be fetched from server and added to recycle view.
I have done coding of same and it is working except one problem that when i choose any option i turn its background green if it is right or i turn it to red if it is wrong but when i do same for any question same action is been transformed on other questions option in recycle view.
As i click on Option A
6th question from previous solved question have option A automatically selected
I am posting my Adapter and Fragment code for same.
Adapter code:-
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(context);
Log.e("I : ", "Creating " );
switch (viewType) {
case QUESTION:
View viewQuestion = inflater.inflate(R.layout.question_card, parent, false);
viewHolder = new QuestionFeed(viewQuestion);
break;
case LOADING:
View viewLoading = inflater.inflate(R.layout.item_progress, parent, false);
viewHolder = new LoadingVH(viewLoading);
break;
}
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final PostRead result = postResults.get(position);
String catname = null;
try {
catname = dataBaseHelper.getCatName(result.getCat());
} catch (SQLException e) {
e.printStackTrace();
}
Log.e("Position: ", "" + position);
switch (getItemViewType(position)) {
case QUESTION:
final QuestionFeed textFeed = (QuestionFeed) holder;
textFeed.question.setText(result.getQuestion());
textFeed.optionA.setText(result.getA());
textFeed.optionB.setText(result.getB());
textFeed.optionC.setText(result.getC());
textFeed.optionD.setText(result.getD());
textFeed.answerView.setText(catname);
textFeed.time.setText("" + TimeAgo.getTimeAgo((10000000000000L - result.getTimestamp())));
textFeed.optionA_layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (result.getAnswer().equals("a")) {
Log.e("AAAAnswer- ", result.getAnswer());
textFeed.optionA_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
} else {
Log.e("Answer- ", result.getAnswer());
textFeed.optionA_layout.setBackgroundColor(context.getResources().getColor(R.color.wrong_answer));
if (result.getAnswer().equals("b")) {
textFeed.optionB_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
} else if (result.getAnswer().equals("c")) {
textFeed.optionC_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
} else if (result.getAnswer().equals("d")) {
textFeed.optionD_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
}
}
if (textFeed.descView.getVisibility() == View.GONE) {
textFeed.descView.setVisibility(View.VISIBLE);
}
}
});
textFeed.optionB_layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (result.getAnswer().equals("b")) {
Log.e("BBBAnswer- ", result.getAnswer());
textFeed.optionB_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
} else {
textFeed.optionB_layout.setBackgroundColor(context.getResources().getColor(R.color.wrong_answer));
if (result.getAnswer().equals("a")) {
textFeed.optionA_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
} else if (result.getAnswer().equals("c")) {
textFeed.optionC_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
} else if (result.getAnswer().equals("d")) {
textFeed.optionD_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
}
}
if (textFeed.descView.getVisibility() == View.GONE) {
textFeed.descView.setVisibility(View.VISIBLE);
}
}
});
textFeed.optionC_layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (result.getAnswer().equals("c")) {
Log.e("CCCAnswer- ", result.getAnswer());
textFeed.optionC_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
} else {
textFeed.optionC_layout.setBackgroundColor(context.getResources().getColor(R.color.wrong_answer));
if (result.getAnswer().equals("b")) {
textFeed.optionB_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
} else if (result.getAnswer().equals("a")) {
textFeed.optionA_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
} else if (result.getAnswer().equals("d")) {
textFeed.optionD_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
}
}
if (textFeed.descView.getVisibility() == View.GONE) {
textFeed.descView.setVisibility(View.VISIBLE);
}
}
});
textFeed.optionD_layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (result.getAnswer().equalsIgnoreCase("d")) {
Log.e("DDDAnswer- ", result.getAnswer());
textFeed.optionD_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
} else {
Log.e("DDDAnswer- ", result.getAnswer());
textFeed.optionD_layout.setBackgroundColor(context.getResources().getColor(R.color.wrong_answer));
if (result.getAnswer().equals("b")) {
textFeed.optionB_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
} else if (result.getAnswer().equals("c")) {
textFeed.optionC_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
} else if (result.getAnswer().equals("a")) {
textFeed.optionA_layout.setBackgroundColor(context.getResources().getColor(R.color.right_answer));
}
}
if (textFeed.descView.getVisibility() == View.GONE) {
textFeed.descView.setVisibility(View.VISIBLE);
}
}
});
break;
}
}
#Override
public int getItemCount() {
return postResults == null ? 0 : postResults.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return QUESTION;
}
public void add(PostRead r) {
postResults.add(r);
notifyItemInserted(postResults.size() - 1);
}
public void addAll(List<PostRead> moveResults) {
for (PostRead result : moveResults) {
add(result);
}
notifyDataSetChanged();
}
public void remove(PostRead r) {
int position = postResults.indexOf(r);
if (position > -1) {
postResults.remove(position);
notifyItemRemoved(position);
}
}
public void clear() {
isLoadingAdded = false;
while (getItemCount() > 0) {
remove(getItem(0));
}
}
public boolean isEmpty() {
return getItemCount() == 0;
}
public void addLoadingFooter() {
isLoadingAdded = true;
add(new PostRead());
}
public void removeLoadingFooter() {
isLoadingAdded = false;
int position = postResults.size() - 1;
PostRead result = getItem(position);
if (result != null) {
postResults.remove(position);
notifyItemRemoved(position);
}
}
public PostRead getItem(int position) {
return postResults.get(position);
}
protected class QuestionFeed extends RecyclerView.ViewHolder {
private ImageView back, share;
private MyTextView question;
private MyTextView optionA, optionB, optionC, optionD, answerView, time;
private LinearLayout optionA_layout, optionB_layout, optionC_layout, optionD_layout, errorLayout, descView;
private ProgressBar mProgress;
private Button btnRetry;
private TextView txtError;
private RelativeLayout mainLayout, backButton;
public QuestionFeed(View itemView) {
super(itemView);
back = (ImageView) itemView.findViewById(R.id.backView);
back = (ImageView) itemView.findViewById(R.id.share);
question = (MyTextView) itemView.findViewById(R.id.question);
optionA = (MyTextView) itemView.findViewById(R.id.optionA);
optionB = (MyTextView) itemView.findViewById(R.id.optionB);
optionC = (MyTextView) itemView.findViewById(R.id.optionC);
optionD = (MyTextView) itemView.findViewById(R.id.optionD);
answerView = (MyTextView) itemView.findViewById(R.id.subject);
time = (MyTextView) itemView.findViewById(R.id.time);
optionA_layout = (LinearLayout) itemView.findViewById(R.id.optionbuttonA);
optionB_layout = (LinearLayout) itemView.findViewById(R.id.optionbuttonB);
optionC_layout = (LinearLayout) itemView.findViewById(R.id.optionbuttonC);
optionD_layout = (LinearLayout) itemView.findViewById(R.id.optionbuttonD);
mProgress = (ProgressBar) itemView.findViewById(R.id.main_progress);
mainLayout = (RelativeLayout) itemView.findViewById(R.id.content_sign_up);
backButton = (RelativeLayout) itemView.findViewById(R.id.back_button);
descView = (LinearLayout) itemView.findViewById(R.id.desc);
errorLayout = (LinearLayout) itemView.findViewById(R.id.error_layout);
btnRetry = (Button) itemView.findViewById(R.id.error_btn_retry);
txtError = (TextView) itemView.findViewById(R.id.error_txt_cause);
}
}
Fragment Code
private void loadFirstPage() {
hideErrorView();
Query query = postRef.orderByChild("timestamp").startAt(firstTime).limitToFirst(14);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
final List<PostRead> allPosts = new ArrayList<>();
childCount = (int) dataSnapshot.getChildrenCount();
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
// TODO: handle the post
Log.e("Online ", "" + firstTime);
PostRead catItems = postSnapshot.getValue(PostRead.class);
catItems.setPostkey(postSnapshot.getKey());
allPosts.add(catItems);
childCount--;
if (childCount == 0) {
firstStart = 0;
dataBaseHelper.updatePosts(allPosts);
hideErrorView();
progressBar.setVisibility(View.GONE);
adapter.addAll(allPosts);
isLoading = false;
if (allPosts.size() == 0) {
isLastPage = true;
} else adapter.addLoadingFooter();
}
firstTime = catItems.getTimestamp();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
That is because Views are recycled by RecyclerView and you are setting background color to different color manually.
The solution is to set default color for background of your textFeed in BindViewHolder as:
textFeed.optionA_layout.setBackgroundColor(context.getResources().getColor(R.color.default_color));
textFeed.optionB_layout.setBackgroundColor(context.getResources().getColor(R.color.default_color));
textFeed.optionC_layout.setBackgroundColor(context.getResources().getColor(R.color.default_color));
textFeed.optionD_layout.setBackgroundColor(context.getResources().getColor(R.color.default_color));
I have a RecycleView where i have three different views for cells. Data is shown perfectly when RView is loaded for the first time. As I start to scroll, it changes the view color. Tried different ways but not able to resolve it.
original view.
wrong view
public class TimelineRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int DATE_LAYOUT = 1;
private static final int EVEN_LAYOUT = 2;
private static final int ODD_LAYOUT = 3;
private List<TimeLineResponseDO.content> contents = new ArrayList<>();
Context context;
LayoutInflater layoutInflater;
private boolean isVisible = false;
private ConnectionDetector connectionDetector;
private ProgressDialog progressDialog;
private Fragment fragment1;
DateFormat inputFormat;
DateFormat outputFormat;
int counterOnCreate = 0;
int counterOnBind = 0;
public interface OpenSubmissionDetails{
void openSubmissionDetails(String submissionId);
}
public interface IGetTimeLineData {
void getTimeLineData(String date);
void loadSnackBar(String msg);
}
public ProgressDialog getProgressDialog(Context context){
if (progressDialog == null) {
progressDialog = new ProgressDialog(context);
progressDialog.setCancelable(false);
progressDialog.setMessage(context.getString(R.string.loading_message));
}
return progressDialog;
}
IGetTimeLineData getTimeLineData;
public IGetTimeLineData getGetTimeLineData() {
return getTimeLineData;
}
public void setGetTimeLineData(IGetTimeLineData getTimeLineData) {
this.getTimeLineData = getTimeLineData;
}
OpenSubmissionDetails openSubmissionDetails;
public OpenSubmissionDetails getOpenSubmissionDetails() {
return openSubmissionDetails;
}
public void setOpenSubmissionDetails(OpenSubmissionDetails openSubmissionDetails) {
this.openSubmissionDetails = openSubmissionDetails;
}
public TimelineRecyclerAdapter(List<TimeLineResponseDO.content> contents, Context context, Fragment fragment, IGetTimeLineData iGetTimeLineData) {
this.contents = contents;
this.context = context;
this.fragment1 = fragment;
this.getTimeLineData = iGetTimeLineData;
layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
connectionDetector = new ConnectionDetector(context);
}
public class TimelineDateHolder extends RecyclerView.ViewHolder{
Button date;
public TimelineDateHolder(View convertView) {
super(convertView);
date = (Button) convertView.findViewById(R.id.date);
}
public void bindViews(TimeLineResponseDO.content response){
Date date1 = null;
try {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("DD-MM-yyyy");
long dateLong = System.currentTimeMillis();
String da = simpleDateFormat.format(dateLong);
Log.e(" Date is :- ", da);
if (response.getDate().equals(da)){
date.setText("Today");
}
else {
if (!TextUtils.isEmpty(response.getDate()))
date.setText(response.getDate());
}
}catch (Exception e){
e.printStackTrace();
if (!TextUtils.isEmpty(response.getDate()))
date.setText(response.getDate());
}
}
}
public class TimelineRecyclerEvenHolder extends RecyclerView.ViewHolder{
RelativeLayout evenContainer;
TextView subjectTypeEven, timingEven, subjectEven, locationEven, teacherEven, cancelTextEven;
Button submissionEven, notificationEven ,submissionEvenDetails ;
ImageView pointerEven, imgCancelBtnEven, imgDelayBtnEven, imgNotificationBtnEven;
View verticalLine;
public TimelineRecyclerEvenHolder(View convertView) {
super(convertView);
evenContainer = (RelativeLayout) convertView.findViewById(R.id.evenContainer);
subjectTypeEven = (TextView) convertView.findViewById(R.id.subjectTypeEven);
timingEven = (TextView) convertView.findViewById(R.id.timingEven);
subjectEven = (TextView) convertView.findViewById(R.id.subjectEven);
locationEven = (TextView) convertView.findViewById(R.id.locationEven);
teacherEven = (TextView) convertView.findViewById(R.id.teacherEven);
pointerEven = (ImageView) convertView.findViewById(R.id.circleEven);
submissionEven = (Button) convertView.findViewById(R.id.submissionEven);
submissionEvenDetails = (Button) convertView.findViewById(R.id.submissionEvenDetails);
imgCancelBtnEven = (ImageView) convertView.findViewById(R.id.cancelBtnEven);//#sp 29-09-2016 added
imgDelayBtnEven = (ImageView) convertView.findViewById(R.id.delayBtnEven);//#sp 30-09-2016 added
imgNotificationBtnEven = (ImageView) convertView.findViewById(R.id.notificationBtnEven);//#sp 30-09-2016 added
notificationEven = (Button) convertView.findViewById(R.id.notificationEven);//#sp 04-10-2016 added
cancelTextEven = (TextView) convertView.findViewById(R.id.cancelTextEven);
subjectTypeEven.setTypeface(NotifyApplication.getExoSemiBold(context));
timingEven.setTypeface(NotifyApplication.getExoSemiBold(context));
subjectEven.setTypeface(NotifyApplication.getExoSemiBold(context));
locationEven.setTypeface(NotifyApplication.getExoSemiBold(context));
teacherEven.setTypeface(NotifyApplication.getExoSemiBold(context));
cancelTextEven.setTypeface(NotifyApplication.getExoSemiBold(context));
}
public void bindViews(TimeLineResponseDO.content response, TimelineRecyclerEvenHolder holder){
holder.evenContainer.setVisibility(View.VISIBLE);
if (!TextUtils.isEmpty(response.getSubjectType())) {
holder.subjectTypeEven.setText(response.getSubjectType());
Log.d("Ifeven", "" + response.getSubjectType());
}
if (response.getLectureSubmission().equals(Enum.LectureSubmission.Submission.toString())) {
holder.subjectTypeEven.setText(Enum.LectureSubmission.Submission.toString());
Log.d("ElseIfeven", "" + response.getSubjectType());
}
Log.d("LectureSubmEven", "" + response.getLectureSubmission());
if (!TextUtils.isEmpty(response.getRoomNo()))
holder.locationEven.setText(response.getRoomNo());
if (!TextUtils.isEmpty(response.getSubject()))
holder.subjectEven.setText(response.getSubject());
if (Boolean.valueOf(StorageService.getInstance().getString("IS_STUDENT")))
{
if (!TextUtils.isEmpty(response.getTeacherAbbreviation()))
holder.teacherEven.setText(response.getTeacherAbbreviation());
}
else if (Boolean.valueOf(StorageService.getInstance().getString("IS_TEACHER")))
{
if (!TextUtils.isEmpty(response.getCourse()))
holder.teacherEven.setText(response.getCourse());
}
if (!TextUtils.isEmpty(response.getStartTime() + context.getString(R.string.timelineHypen) + response.getEndTime()))
holder.timingEven.setText(response.getStartTime() + context.getString(R.string.timelineHypen) + response.getEndTime());
holder.pointerEven.setBackgroundResource(R.drawable.timeline_pointer_left);
holder.timingEven.setCompoundDrawablesWithIntrinsicBounds(R.drawable.timeline_timing, 0, 0, 0);
Log.d("resp isSubmission", "" + response.isSubmission());
if (response.isSubmission()) {
holder.submissionEven.setVisibility(View.VISIBLE);
holder.submissionEven.setText(response.getSubmissionCount() + " Submission");
} else {
holder.submissionEven.setVisibility(View.GONE);
}
Log.d("resp Noti", "" + response.isNotiification());
if (response.isNotiification()) {
holder.notificationEven.setVisibility(View.VISIBLE);
} else {
holder.notificationEven.setVisibility(View.GONE);
}
if (response.getLectureSubmission().equals("Submission")) {
holder.submissionEvenDetails.setVisibility(View.VISIBLE);
} else {
holder.submissionEvenDetails.setVisibility(View.GONE);
}
if (response.isCancelled()) {
ChangeFontColorEven(holder);
}
if (response.getSubmissionStatus() != null) {
if (response.getSubmissionStatus().equals("No")) {
ChangeFontColorEven(holder);
}
}
if (response.isEvenLayout()) {
if (response.getLectureSubmission().equals("Submission")) {
holder.imgDelayBtnEven.setImageResource(R.drawable.pencil);
} else {
holder.imgDelayBtnEven.setImageResource(R.drawable.delay);
}
}
if (!TextUtils.isEmpty(response.getTrnLectureId())) {
submissionLoadId(response);
}
holder.notificationEven.setText(response.getNotificationCount() + " Notifications");
if (isVisible) {
if (!response.isDateContainer()) {
if (response.getLectureSubmission().equals("Submission") && !TextUtils.isEmpty(response.getLectureSubmission())) {
if (response.getSubmissionStatus().equals("No")) {
ShowHideEditLectureIconsEven(holder, View.GONE);
} else {
ShowHideEditLectureIconsEven(holder, View.VISIBLE);
}
} else {
if (response.isCancelled()) {
ShowHideEditLectureIconsEven(holder, View.GONE);
} else {
ShowHideEditLectureIconsEven(holder, View.VISIBLE);
}
}
}
}else {
ShowHideEditLectureIconsEven(holder, View.GONE);
}
}
}
public class TimelineRecyclerHolder extends RecyclerView.ViewHolder{
RelativeLayout oddContainer;
TextView subjectTypeOdd, timingOdd, subjectOdd, locationOdd, teacherOdd, tvCancelTextOdd;
Button submissionOdd, notificationOdd , submissionOddDetails;
ImageView pointerOdd, imgCancelBtnOdd, imgDelayBtnOdd, imgNotificationBtnOdd;
View verticalLine;
public TimelineRecyclerHolder(View convertView) {
super(convertView);
oddContainer = (RelativeLayout) convertView.findViewById(R.id.oddContainer);
subjectTypeOdd = (TextView) convertView.findViewById(R.id.subjectTypeOdd);
timingOdd = (TextView) convertView.findViewById(R.id.timingOdd);
subjectOdd = (TextView) convertView.findViewById(R.id.subjectOdd);
locationOdd = (TextView) convertView.findViewById(R.id.locationOdd);
teacherOdd = (TextView) convertView.findViewById(R.id.teacherOdd);
pointerOdd = (ImageView) convertView.findViewById(R.id.circleOdd);
submissionOdd = (Button) convertView.findViewById(R.id.submissionOdd);
submissionOddDetails = (Button) convertView.findViewById(R.id.submissionOddDetails);
imgCancelBtnOdd = (ImageView) convertView.findViewById(R.id.cancelBtnOdd);
imgDelayBtnOdd = (ImageView) convertView.findViewById(R.id.delayBtnOdd);
imgNotificationBtnOdd = (ImageView) convertView.findViewById(R.id.notificationBtnOdd);
notificationOdd = (Button) convertView.findViewById(R.id.notificationOdd);
tvCancelTextOdd = (TextView) convertView.findViewById(R.id.cancelTextOdd);
subjectTypeOdd.setTypeface(NotifyApplication.getExoSemiBold(context));
timingOdd.setTypeface(NotifyApplication.getExoSemiBold(context));
subjectOdd.setTypeface(NotifyApplication.getExoSemiBold(context));
locationOdd.setTypeface(NotifyApplication.getExoSemiBold(context));
teacherOdd.setTypeface(NotifyApplication.getExoSemiBold(context));
tvCancelTextOdd.setTypeface(NotifyApplication.getExoSemiBold(context));
}
public void bindViews(TimeLineResponseDO.content response, TimelineRecyclerHolder holder){
//holder.verticalLine.setVisibility(View.VISIBLE);
holder.oddContainer.setVisibility(View.VISIBLE);
if (!TextUtils.isEmpty(response.getSubjectType())) {
holder.subjectTypeOdd.setText(response.getSubjectType());
}
if (response.getLectureSubmission().equals(Enum.LectureSubmission.Submission.toString())) {
holder.subjectTypeOdd.setText(Enum.LectureSubmission.Submission.toString());
}
if (!TextUtils.isEmpty(response.getRoomNo()))
holder.locationOdd.setText(response.getRoomNo());
if (!TextUtils.isEmpty(response.getSubject()))
holder.subjectOdd.setText(response.getSubject());
if (Boolean.valueOf(StorageService.getInstance().getString("IS_STUDENT")))
{
if (!TextUtils.isEmpty(response.getTeacherAbbreviation()))
holder.teacherOdd.setText(response.getTeacherAbbreviation());
}
else if (Boolean.valueOf(StorageService.getInstance().getString("IS_TEACHER")))
{
if (!TextUtils.isEmpty(response.getCourse()))
holder.teacherOdd.setText(response.getCourse());
}
if (!TextUtils.isEmpty(response.getStartTime() + context.getString(R.string.timelineHypen) + response.getEndTime()))
holder.timingOdd.setText(response.getStartTime() + context.getString(R.string.timelineHypen) + response.getEndTime());
holder.pointerOdd.setBackgroundResource(R.drawable.timeline_pointer_right);
holder.timingOdd.setCompoundDrawablesWithIntrinsicBounds(R.drawable.timeline_timing, 0, 0, 0);
if (response.isSubmission()) {
holder.submissionOdd.setVisibility(View.VISIBLE);
holder.submissionOdd.setText(response.getSubmissionCount() + " Submission");
} else {
holder.submissionOdd.setVisibility(View.GONE);
}
if (response.isNotiification()) {
holder.notificationOdd.setVisibility(View.VISIBLE);
} else {
holder.notificationOdd.setVisibility(View.GONE);
}
if (response.getLectureSubmission().equals("Submission")) {
holder.submissionOddDetails.setVisibility(View.VISIBLE);
} else {
holder.submissionOddDetails.setVisibility(View.GONE);
}
if (response.isCancelled()) {
ChangeFontColor(holder, Enum.LayoutType.Odd);
}
if (response.getSubmissionStatus() != null) {
if (response.getSubmissionStatus().equals("No")) {
ChangeFontColor(holder, Enum.LayoutType.Odd);
}
}
if (response.getLectureSubmission().equals("Submission")) {
holder.imgDelayBtnOdd.setImageResource(R.drawable.pencil);
} else {
holder.imgDelayBtnOdd.setImageResource(R.drawable.delay);
}
if (!TextUtils.isEmpty(response.getTrnLectureId())) {
submissionLoadId(response);
}
holder.notificationOdd.setText(response.getNotificationCount() + " Notifications");
if (isVisible) {
if (!response.isDateContainer()) {
if (response.getLectureSubmission().equals("Submission") && !TextUtils.isEmpty(response.getLectureSubmission())) {
if (response.getSubmissionStatus().equals("No")) {
ShowHideEditLectureIcons(holder, View.GONE);
} else {
ShowHideEditLectureIcons(holder, View.VISIBLE);
}
} else {
if (response.isCancelled()) {
ShowHideEditLectureIcons(holder, View.GONE);
} else {
ShowHideEditLectureIcons(holder, View.VISIBLE);
}
}
}
}else {
ShowHideEditLectureIcons(holder, View.GONE);
}
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType){
case DATE_LAYOUT:
View convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.timeline_date_header, parent, false);
return new TimelineDateHolder(convertView);
case EVEN_LAYOUT:
View convertView1 = LayoutInflater.from(parent.getContext()).inflate(R.layout.timeline_even_layout_child, parent, false);
return new TimelineRecyclerEvenHolder(convertView1);
default:
View convertView2 = LayoutInflater.from(parent.getContext()).inflate(R.layout.timeline_odd_layout_child, parent, false);
return new TimelineRecyclerHolder(convertView2);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final int itemType = getItemViewType(position);
TimeLineResponseDO.content content = contents.get(position);
switch (itemType){
case DATE_LAYOUT:
((TimelineDateHolder) holder).bindViews(content);
break;
case EVEN_LAYOUT:
((TimelineRecyclerEvenHolder) holder).bindViews(content, (TimelineRecyclerEvenHolder) holder);
break;
default:
((TimelineRecyclerHolder) holder).bindViews(content, (TimelineRecyclerHolder) holder);
break;
}
if (position == (contents.size() - 1)) {
if (connectionDetector.isConnectingToInternet()) {
getTimeLineData.getTimeLineData(content.getContentDate());
}
else {
getTimeLineData.loadSnackBar(context.getString(R.string.no_internet_connection_schedule));
}
}
}
#Override
public int getItemCount() {
return contents.size();
}
#Override
public int getItemViewType(int position) {
if (contents.get(position).isDateContainer()){
return DATE_LAYOUT;
}
else if (contents.get(position).isEvenLayout()){
return EVEN_LAYOUT;
}
else {
return ODD_LAYOUT;
}
}
private void ChangeFontColor(TimelineRecyclerHolder holder, Enum.LayoutType layoutType) {
switch (layoutType){
case Even:
break;
case Odd:
holder.subjectTypeOdd.setTextColor(context.getResources().getColor(android.R.color.holo_red_dark));
holder.timingOdd.setTextColor(context.getResources().getColor(android.R.color.holo_red_dark));
holder.pointerOdd.setBackgroundResource(R.drawable.timeline_pointer_right_red);
holder.subjectOdd.setTextColor(context.getResources().getColor(android.R.color.holo_red_dark));
holder.locationOdd.setVisibility(View.GONE);
holder.teacherOdd.setVisibility(View.GONE);
holder.tvCancelTextOdd.setVisibility(View.VISIBLE);
holder.tvCancelTextOdd.setTextColor(context.getResources().getColor(android.R.color.holo_red_dark));
holder.submissionOdd.setVisibility(View.GONE);
holder.submissionOddDetails.setVisibility(View.GONE);
break;
}
}
private void ChangeFontColorEven(TimelineRecyclerEvenHolder holder) {
holder.subjectTypeEven.setTextColor(context.getResources().getColor(android.R.color.holo_red_dark));
holder.timingEven.setTextColor(context.getResources().getColor(android.R.color.holo_red_dark));
holder.pointerEven.setBackgroundResource(R.drawable.timeline_pointer_left_red);
holder.subjectEven.setTextColor(context.getResources().getColor(android.R.color.holo_red_dark));
holder.locationEven.setVisibility(View.GONE);
holder.teacherEven.setVisibility(View.GONE);
holder.cancelTextEven.setVisibility(View.VISIBLE);
holder.cancelTextEven.setTextColor(context.getResources().getColor(android.R.color.holo_red_dark));
holder.submissionEven.setVisibility(View.GONE);
holder.submissionEvenDetails.setVisibility(View.GONE);
}
private void ShowHideEditLectureIcons(TimelineRecyclerHolder holder, int visibility) {
holder.imgCancelBtnOdd.setVisibility(visibility);
holder.imgDelayBtnOdd.setVisibility(visibility);
holder.imgNotificationBtnOdd.setVisibility(visibility);
}
private void ShowHideEditLectureIconsEven(TimelineRecyclerEvenHolder holder, int visibility) {
holder.imgCancelBtnEven.setVisibility(visibility);
holder.imgDelayBtnEven.setVisibility(visibility);
holder.imgNotificationBtnEven.setVisibility(visibility);
}
public void editEvent(boolean isVisible) {
this.isVisible = isVisible;
Log.d("Is Visible", String.valueOf(isVisible));
notifyDataSetChanged();
}
public void submission(final TimeLineResponseDO.content timeLineModel) {
final IGetSubmissionDetails iGetSubmissionDetails = new GetSubmissionDetailsBO();
iGetSubmissionDetails.getSubmissionByTrn(context, timeLineModel.getTrnLectureId(), new Response<ArrayList<String>>() {
#Override
public void onSuccess(ArrayList<String> callback) throws IOException {
StorageService.getInstance().putString("SubmissionId", callback.get(0));
FragmentManager fragmentManager = ((AppCompatActivity) context).getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
NoticeBoard noticeBoard = new NoticeBoard();
Bundle bundle = new Bundle();
bundle.putStringArrayList("submissionIds", callback);
bundle.putString("submissionId",callback.get(0));
bundle.putString("isFrom","submission_view");
noticeBoard.setArguments(bundle);
fragmentTransaction.replace(R.id.container, noticeBoard, NoticeBoard.class.getSimpleName());
fragmentTransaction.addToBackStack(NoticeBoard.class.getSimpleName());
fragmentTransaction.commit();
}
#Override
public void onError(Exception e, int i, String msg) {
Log.d("trnId error",e.toString());
}
});
}
public void submissionLoadId(final TimeLineResponseDO.content timeLineModel) {
final IGetSubmissionDetails iGetSubmissionDetails = new GetSubmissionDetailsBO();
iGetSubmissionDetails.getSubmissionByTrn(context, timeLineModel.getTrnLectureId(), new ResponseNew<ArrayList<String>>() {
#Override
public void onSuccess(ArrayList<String> callback, String id) throws IOException {
for (int i = 0; i < callback.size(); i++){
Log.e("trnId error", id + " " + callback.get(i));
if (AppConstant.initializeDbORReturn(context).isSubmissionIdExists(id, callback.get(i))){
Log.e("Already Exists :- ", id + " " + callback.get(i));
}
else {
AppConstant.initializeDbORReturn(context).insertSubmissionId(id, callback.get(i));
}
}
}
#Override
public void onError(Exception e, int i, String msg) {
}
});
}
private void localTimeLinedb(List<TimeLineResponseDO> callback, Context context) {
for (int i = 0; i < callback.size(); i++) {
TimeLineResponseDO timeLineResponseDO = callback.get(i);
for (int j = 0; j < timeLineResponseDO.getContentList().size(); j++) {
TimeLineResponseDO.content content = timeLineResponseDO.getContentList().get(j);
if (AppConstant.initializeDbORReturn(context).isTimeLineExits(timeLineResponseDO.getDate(),
content.getStaticLectureId(), content.getDate(),
content.getTrnLectureId(), content.getSlotId(), content.getSubject(),
content.getSubmissionId(), content.getLectureSubmission())) {
AppConstant.initializeDbORReturn(context).updateTimeLine(content, timeLineResponseDO.getDate());
} else {
AppConstant.initializeDbORReturn(context).insertIntoTimeLine(content, timeLineResponseDO.getDate());
}
}
}
}
public void getTimeLineData(String date, final Context context, final TimelineRecyclerHolder holder, final Enum.LayoutType even_odd, final Enum.EditLectureType editLectureType) {
inputFormat = new SimpleDateFormat("dd-mm-yyyy");
outputFormat = new SimpleDateFormat("yyyy-mm-dd");
ITimeLine timeLine = new TimeLineBO();
TimeLinePostDO timeLinePostDO = new TimeLinePostDO();
if (date == null) {
if (!TextUtils.isEmpty(StorageService.getInstance().getString("Running_Teacher_Id"))){
timeLinePostDO.setUserId(StorageService.getInstance().getString("Running_Teacher_Id"));
}
else {
timeLinePostDO.setUserId(StorageService.getInstance().getString("NEWUSER_ID"));
}
timeLinePostDO.setUserRoles(StorageService.getInstance().getString("USER_ROLES"));
} else {
if (!TextUtils.isEmpty(StorageService.getInstance().getString("Running_Teacher_Id"))){
timeLinePostDO.setUserId(StorageService.getInstance().getString("Running_Teacher_Id"));
}
else {
timeLinePostDO.setUserId(StorageService.getInstance().getString("NEWUSER_ID"));
}
timeLinePostDO.setUserRoles(StorageService.getInstance().getString("USER_ROLES"));
try {
timeLinePostDO.setDate(outputFormat.format(inputFormat.parse(date)));
} catch (ParseException e) {
e.printStackTrace();
}
}
timeLine.getTimeLineData(context, timeLinePostDO, new Response<List<TimeLineResponseDO>>() {
#Override
public void onSuccess(List<TimeLineResponseDO> callback) {
localTimeLinedb(callback, context);
getProgressDialog(context).dismiss();
switch (editLectureType){
case Cancel:
ChangeFontColor(holder, even_odd);
Toast.makeText(context, "Lecture Cancelled", Toast.LENGTH_SHORT).show();
ShowHideEditLectureIcons(holder, View.GONE);
break;
case Delay:
Toast.makeText(context, "Notification sent for delay", Toast.LENGTH_SHORT).show();
break;
case CreateNotification:
Toast.makeText(context, "Notification sent", Toast.LENGTH_SHORT).show();
break;
}
if (fragment1 instanceof TimeLineFragment){
((TimeLineFragment) fragment1).refreshList();
}
}
#Override
public void onError(Exception e, int i, String msg) {
}
});
}
}
Thanks in advance !
RecyclerViewAdapter recycles its views and thus the behavior is much expected.
When I read your code I saw that you've written if statements without else like :
if (!TextUtils.isEmpty(response.getRoomNo()))
holder.locationEven.setText(response.getRoomNo());
if (!TextUtils.isEmpty(response.getSubject()))
holder.subjectEven.setText(response.getSubject());
These will be reused if the view in the position before the newly loaded view doesn't fulfill that if statement.
Try adding else to your every if statement. By adding else I mean add something like
else {
holder.locationEven.setText("");
}
// OR
else {
holder.locationEven.setVisibility(View.GONE);
}