I am using MVVM pattern with retrofit and recyclerview for the first time. I have made the network call in my viewmodel class but have no idea how to display the data in recyclerview.
Here's my viewmodel code:
public class HomeSessionsViewModel extends ViewModel {
private static final String TAG = HomeSessionsViewModel.class.getSimpleName();
private Context context;
public String sessionImg;
public String title, programName, batchName, batchPlayersCount;
public HomeSessionsViewModel(Context context) {
this.context = context;
}
public void fetchSessions(String coachId){
Log.d(TAG, "Call made");
Call<SessionDetails> call = RestClient.getRestInstance()
.getSessionsService()
.fetchSessions(coachId);
call.enqueue(new Callback<SessionDetails>() {
#Override
public void onResponse(Call<SessionDetails> call, Response<SessionDetails> response) {
if (response.isSuccessful()){
SessionDetails details = response.body();
List<Sessions> sessions = details.getSessions();
for (int i = 0; i < sessions.size(); i++){
Log.d(TAG, "Session Name:\t" + sessions.get(i).session_name);
sessionImg = sessions.get(i).sessionImage;
title = sessions.get(i).session_name;
programName = sessions.get(i).program_name;
batchName = sessions.get(i).batch_name;
batchPlayersCount = sessions.get(i).participants_count;
// addData(sessions);
}
}
}
#Override
public void onFailure(Call<SessionDetails> call, Throwable t) {
Log.d(TAG, "Can't Get Sessions:\n");
Log.d(TAG, t.getMessage());
}
});
}
}
and adapter code:
public class SessionsAdapter extends RecyclerView.Adapter<SessionsViewHolder> {
private final Context context;
private List<HomeSessionsViewModel> itemsList;
public SessionsAdapter(Context context, List<HomeSessionsViewModel> itemsList) {
this.context = context;
this.itemsList = itemsList;
}
#Override
public SessionsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
HomeSessionsBinding sessionsBinding = HomeSessionsBinding.inflate(inflater, parent, false);
return new SessionsViewHolder(sessionsBinding);
}
#Override
public void onBindViewHolder(SessionsViewHolder viewholder, int position) {
HomeSessionsViewModel viewModel = itemsList.get(position);
viewholder.bindSessions(viewModel);
}
#Override
public int getItemCount() {
if (itemsList == null) {
return 0;
}
return itemsList.size();
}
}
and in my fragment I have this:
public class HomeFragment extends Fragment implements OnItemClickedListener, DatePickerListener {
private RecyclerView actionsRV, sessionsRV;
private List<ActionsViewModel> actionsList = new ArrayList<>();
private ActionsAdapter actionsAdapter;
private HomeFragmentBinding fragmentBinding;
private HomeFragmentViewModel homeViewModel;
private HomeSessionsViewModel sessionsViewModel;
private List<HomeSessionsViewModel> sessionsViewModelList = new ArrayList<>();
private SessionsAdapter sessionsAdapter;
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
fragmentBinding = DataBindingUtil.inflate(inflater, R.layout.home_fragment, container, false);
homeViewModel = new HomeFragmentViewModel(getActivity());
fragmentBinding.setHomeViewModel(homeViewModel);
init();
return fragmentBinding.getRoot();
}
private void init() {
addActions();
initPicker();
populateSessions();
}
private void initPicker() {
fragmentBinding.datePicker.setListener(this)
.setMonthAndYearTextColor(getActivity().getResources().getColor(R.color.white))
.setDateSelectedColor(getActivity().getResources().getColor(R.color.white))
.setDateSelectedTextColor(getActivity().getResources().getColor(R.color.event_color_03))
.setTodayButtonTextColor(getActivity().getResources().getColor(R.color.white))
.setTodayDateTextColor(getActivity().getResources().getColor(R.color.accent))
.setUnselectedDayTextColor(getActivity().getResources().getColor(R.color.white))
.init();
}
private void populateSessions() {
sessionsViewModel = ViewModelProviders.of(this).get(HomeSessionsViewModel.class);
sessionsViewModel.fetchSessions("4086");
//sessionsViewModel.fetchSessions();
//sessionsViewModel.fetchSessions(""); // TODO: 3/16/2019 Use coach id from db
sessionsRV = fragmentBinding.sessionsRV;
//sessionsViewModelList = sessionsViewModel.items();
sessionsAdapter = new SessionsAdapter(getActivity(), sessionsViewModelList);
}
private void addActions() {
actionsRV = fragmentBinding.actionsRV;
actionsRV.setHasFixedSize(true);
LinearLayoutManager hlm = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
fragmentBinding.actionsRV.setLayoutManager(hlm);
ActionsViewModel action1 = new ActionsViewModel();
action1.name = "Attendance";
action1.img = getResources().getDrawable(R.drawable.ic_attendance);
actionsList.add(action1);
ActionsViewModel action2 = new ActionsViewModel();
action2.name = "Evaluate";
action2.img = getResources().getDrawable(R.drawable.ic_evaluate);
actionsList.add(action2);
ActionsViewModel action3 = new ActionsViewModel();
action3.name = "Players";
action3.img = getResources().getDrawable(R.drawable.ic_players);
actionsList.add(action3);
ActionsViewModel action4 = new ActionsViewModel();
action4.name = "Programs";
action4.img = getResources().getDrawable(R.drawable.ic_programs);
actionsList.add(action4);
ActionsViewModel action5 = new ActionsViewModel();
action5.name = "Tips/VOD";
action5.img = getResources().getDrawable(R.drawable.ic_tips_vod);
actionsList.add(action5);
actionsAdapter = new ActionsAdapter(getActivity(), actionsList);
actionsAdapter.setItemClickedListener(this);
actionsRV.setAdapter(actionsAdapter);
}
#Override
public void itemClicked(int position) {
switch (position){
case 0:
Toast.makeText(getActivity(), "Attendance Clicked", Toast.LENGTH_SHORT).show();
break;
case 1:
Toast.makeText(getActivity(), "Evaluate Clicked", Toast.LENGTH_SHORT).show();
break;
case 2:
Toast.makeText(getActivity(), "Players Clicked", Toast.LENGTH_SHORT).show();
break;
case 3:
Toast.makeText(getActivity(), "Programs Clicked", Toast.LENGTH_SHORT).show();
break;
case 4:
Snackbar.make(getActivity().findViewById(android.R.id.content), "Tips Coming Soon", Snackbar.LENGTH_SHORT).show();
break;
}
}
#Override
public void onDateSelected(DateTime dateSelected) {
}
}
Displaying the actions recyclerview was straightforward but I'm not sure how to go about the sessions. I have followed this tutorial series but I'm stuck how to get the data from viewmodel into fragment recyclerview. I have read that adding view widgets into viewmodel can cause memory leaks. Is there any way to do this? Thanks.
You can use LiveData for these kind of purposes. LiveData is Lifecycle aware and can be used in ViewModel.
In your ViewModel, add a property of type MutableLiveData.
private MutableLiveData<List<Session>> sessionsLiveData = new MutableLiveData<List<Session>>();
public LiveData<List<Session>> getSessionLiveData(){
return sessionsLiveData;
}
Set value to this LiveData when network call is made and you have required data for the adapter.
call.enqueue(new Callback<SessionDetails>() {
#Override
public void onResponse(Call<SessionDetails> call, Response<SessionDetails> response) {
if (response.isSuccessful()){
SessionDetails details = response.body();
List<Session> sessions = details.getSessions();
sessionsLiveData.postValue(sessions);
}
}
#Override
public void onFailure(Call<SessionDetails> call, Throwable t) {
Log.d(TAG, "Can't Get Sessions:\n");
Log.d(TAG, t.getMessage());
}
});
In your Fragment, observer this LiveData.
viewModel.getSessionLiveData().observe(this, new Observer<List<Session>>() {
#Override
public void onChanged(#Nullable final List<Session> sessions) {
// set Data to adapter here.
adapter.setData(sessions);
}
});
Related
I am trying to let my RecyclerView show the 'Message-rooms' items after I receive it from the server.
Currently, RecyclerView is on Fragment which is connected to BottomNavigationView.
I used 'MessageRoomAdapter' to set informations from the server response, but somehow, after successful communication, my RecyclerView shows just empty(white) screen.
Is it related to lifecycle problem?
I googled it for hours, but couldn't find answer.
MessageRoomAdapter.java
public class MessageRoomAdapter extends RecyclerView.Adapter<MessageRoomAdapter.CustomViewHolder> {
private ArrayList<MessageRoomItem> message_room_item_list;
private OnItemClickListener mListener = null;
public MessageRoomAdapter(ArrayList<MessageRoomItem> message_room_item_list) {
this.message_room_item_list = message_room_item_list;
}
public interface OnItemClickListener {
void onItemClick(View v, int position);
}
#NonNull
#Override
public MessageRoomAdapter.CustomViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message_room, parent, false);
CustomViewHolder holder = new CustomViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull MessageRoomAdapter.CustomViewHolder holder, int position) {
holder.tv_item_message_room_idx.setText(Integer.toString(message_room_item_list.get(position).getMessage_room_idx()));
holder.tv_item_message_user_idx.setText(Integer.toString(message_room_item_list.get(position).getUser_idx()));
holder.tv_item_message_user_nickname.setText(message_room_item_list.get(position).getUser_nickname());
holder.tv_item_message_message_idx.setText(Integer.toString(message_room_item_list.get(position).getMessage_idx()));
holder.tv_item_message_content.setText(message_room_item_list.get(position).getContent());
holder.tv_item_message_time.setText(message_room_item_list.get(position).getTime());
holder.itemView.setTag(position);
}
#Override
public int getItemCount() {
return (null != message_room_item_list ? message_room_item_list.size() : 0);
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
protected TextView tv_item_message_user_nickname;
protected TextView tv_item_message_time;
protected TextView tv_item_message_content;
protected TextView tv_item_message_room_idx;
protected TextView tv_item_message_user_idx;
protected TextView tv_item_message_message_idx;
public CustomViewHolder(#NonNull final View itemView) {
super(itemView);
this.tv_item_message_user_nickname = itemView.findViewById(R.id.tv_item_message_user_nickname);
this.tv_item_message_time = itemView.findViewById(R.id.tv_item_message_time);
this.tv_item_message_content = itemView.findViewById(R.id.tv_item_message_content);
this.tv_item_message_room_idx = itemView.findViewById(R.id.tv_item_message_room_idx);
this.tv_item_message_user_idx = itemView.findViewById(R.id.tv_item_message_user_idx);
this.tv_item_message_message_idx = itemView.findViewById(R.id.tv_item_message_message_idx);
}
}
}
MainActivity.java
public class MainActivity extends BaseActivity implements MainActivityView {
private long mBackKeyPressedTime = 0;
private Toast mToast;
BottomNavigationView bottom_navigation_view_main;
FragmentAgora fragmentAgora;
FragmentRestaurant fragmentRestaurant;
FragmentMessage fragmentMessage;
FragmentMyPage fragmentMyPage;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bottom_navigation_view_main = findViewById(R.id.bottom_navigation_view_main);
fragmentAgora = new FragmentAgora();
fragmentRestaurant = new FragmentRestaurant();
fragmentMessage = new FragmentMessage();
fragmentMyPage = new FragmentMyPage();
getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_main, fragmentAgora).commitAllowingStateLoss();
bottom_navigation_view_main.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
switch (menuItem.getItemId()) {
case R.id.item_agora_main: {
getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_main, fragmentAgora).commitAllowingStateLoss();
return true;
}
case R.id.item_restaurant_main: {
getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_main, fragmentRestaurant).commitAllowingStateLoss();
return true;
}
case R.id.item_message_main: {
getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_main, fragmentMessage).commitAllowingStateLoss();
return true;
}
case R.id.item_mypage_main: {
getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout_main, fragmentMyPage).commitAllowingStateLoss();
return true;
}
default:
return false;
}
}
});
}
FragmentMessage.java
public class FragmentMessage extends Fragment implements FragmentMessageView{
ViewGroup viewGroup;
private ArrayList<MessageRoomItem> m_message_room_item_list;
private MessageRoomAdapter messageRoomAdapter;
private RecyclerView rv_message_box;
private LinearLayoutManager linear_layout_manager;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
viewGroup = (ViewGroup) inflater.inflate(R.layout.frag_message, container, false);
rv_message_box = viewGroup.findViewById(R.id.rv_message_box_message_list);
linear_layout_manager = new LinearLayoutManager(viewGroup.getContext());
rv_message_box.setLayoutManager(linear_layout_manager);
m_message_room_item_list = new ArrayList<>();
messageRoomAdapter = new MessageRoomAdapter(m_message_room_item_list);
rv_message_box.setAdapter(messageRoomAdapter);
trygetMessageList();
return viewGroup;
}
private void trygetMessageList() {
final FragmentMessageService fragmentMessageService = new FragmentMessageService(this);
fragmentMessageService.getMessageRoomList();
}
#Override
public void getMessageRoomListSuccess(MessageRoomResponse messageRoomResponse) {
Toast.makeText(getContext(), messageRoomResponse.getMessage(), Toast.LENGTH_SHORT).show();
switch (messageRoomResponse.getCode()){
default:
System.out.println(messageRoomResponse.getMessage());
loadMessageRooms(messageRoomResponse);
}
}
public void loadMessageRooms(MessageRoomResponse messageRoomResponse){
switch (messageRoomResponse.getCode()){
case 100:
int num_of_message_rooms = messageRoomResponse.getMessageRoomResults().size();
for (int i = 0; i < num_of_message_rooms; i++){
MessageRoomItem messageRoomItem = new MessageRoomItem();
messageRoomItem.setMessage_room_idx(messageRoomResponse.getMessageRoomResults().get(i).getMessage_room_idx());
messageRoomItem.setUser_idx(messageRoomResponse.getMessageRoomResults().get(i).getUser_idx());
messageRoomItem.setUser_nickname(messageRoomResponse.getMessageRoomResults().get(i).getUser_nickname());
messageRoomItem.setMessage_idx(messageRoomResponse.getMessageRoomResults().get(i).getMessage_idx());
messageRoomItem.setContent(messageRoomResponse.getMessageRoomResults().get(i).getContent());
messageRoomItem.setTime(messageRoomResponse.getMessageRoomResults().get(i).getTime());
m_message_room_item_list.add(messageRoomItem);
}
break;
default:
break;
}
}
}
FragmentMessageService.java
public class FragmentMessageService {
private final FragmentMessageView mFragmentMessageView;
private HashMap<String, Object> mParams;
public FragmentMessageService(final FragmentMessageView fragmentMessageView) {
this.mFragmentMessageView = fragmentMessageView;
}
public FragmentMessageService(FragmentMessageView mFragmentMessageView, HashMap<String, Object> mParams) {
this.mFragmentMessageView = mFragmentMessageView;
this.mParams = mParams;
}
void getMessageRoomList() {
final FragmentMessageRetrofitInterface fragmentMessageRetrofitInterface = getRetrofit().create(FragmentMessageRetrofitInterface.class);
fragmentMessageRetrofitInterface.getMessageRoomList(X_ACCESS_TOKEN).enqueue(new Callback<MessageRoomResponse>() {
#Override
public void onResponse(Call<MessageRoomResponse> call, Response<MessageRoomResponse> response) {
final MessageRoomResponse messageRoomResponse = response.body();
if (messageRoomResponse == null) {
mFragmentMessageView.validateFailure(null);
return;
}
mFragmentMessageView.getMessageRoomListSuccess(messageRoomResponse);
}
#Override
public void onFailure(Call<MessageRoomResponse> call, Throwable t) {
mFragmentMessageView.validateFailure(null);
}
});
}
You are creating an empty list of m_message_room_item_list and setting that list to Adapter, then you are actually loading the list, but never updating the Adapter.
What you should do is create a method inside adapter like:
public void setList(ArrayList<MessageRoomItem> message_room_item_list) {
this.message_room_item_list = message_room_item_list;
notifyDataSetChanged();
}
and then call it in loadMessageRooms() perhaps, like:
public void loadMessageRooms(MessageRoomResponse messageRoomResponse){
switch (messageRoomResponse.getCode()){
case 100:
int num_of_message_rooms = messageRoomResponse.getMessageRoomResults().size();
for (int i = 0; i < num_of_message_rooms; i++){
MessageRoomItem messageRoomItem = new MessageRoomItem();
messageRoomItem.setMessage_room_idx(messageRoomResponse.getMessageRoomResults().get(i).getMessage_room_idx());
messageRoomItem.setUser_idx(messageRoomResponse.getMessageRoomResults().get(i).getUser_idx());
messageRoomItem.setUser_nickname(messageRoomResponse.getMessageRoomResults().get(i).getUser_nickname());
messageRoomItem.setMessage_idx(messageRoomResponse.getMessageRoomResults().get(i).getMessage_idx());
messageRoomItem.setContent(messageRoomResponse.getMessageRoomResults().get(i).getContent());
messageRoomItem.setTime(messageRoomResponse.getMessageRoomResults().get(i).getTime());
m_message_room_item_list.add(messageRoomItem);
}
messageRoomAdapter.setList(m_message_room_item_list);
break;
default:
break;
}
}
I use retrofit2 to import data from each of the three tables.
Put the values in one list and show them in RecycleView.
But it shows the first result from the second run.
The second result shows from the third run.
The first run is nothing.
In the first run, Adapter's list.size() also gives zero.
I don't know why.
It's MainActivity.
public class HistoryActivity extends AppCompatActivity implements View.OnClickListener {
private TextView foodTextView, companyTextView, dateTextView, useMaterialTextView;
private ImageView dateChangeImgView;
Calendar calendar;
RecyclerView historyRecyclerView;
ApiInterface apiInterface;
RecyclerView.LayoutManager layoutManager;
List<CowInfoData> cowInfoDataList;
List<RiceInfoData> riceInfoDataList;
List<VegetableInfoData> vegetableInfoDataList;
List list = new ArrayList();
HistoryAdapter historyAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_history);
HistoryActivityInit();
Intent intent = getIntent();
String foodName = intent.getExtras().getString("food_name");
String companyName = intent.getExtras().getString("company_name");
foodTextView.setText(foodName);
companyTextView.setText(companyName);
}
private void HistoryActivityInit() {
foodTextView = findViewById(R.id.text_food_name);
companyTextView = findViewById(R.id.text_company_name);
dateChangeImgView = findViewById(R.id.imgview_date_change);
dateTextView = findViewById(R.id.text_date);
useMaterialTextView = findViewById(R.id.text_use_material);
historyRecyclerView = findViewById(R.id.recyclerview_history);
calendar = new GregorianCalendar();
// dateTextView.setText(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
layoutManager = new LinearLayoutManager(this);
historyRecyclerView.setLayoutManager(layoutManager);
historyRecyclerView.setHasFixedSize(true);
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.imgview_date_change:
chooseDate();
break;
}
}
private void chooseDate() {
final View dialogView = View.inflate(this, R.layout.dialog_date_picker, null);
final DatePicker datePicker = dialogView.findViewById(R.id.date_picker);
datePicker.updateDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(dialogView);
builder.setNegativeButton("Cancel", null);
builder.setPositiveButton("Ok", (dialog, which) -> {
calendar = new GregorianCalendar(datePicker.getYear(), datePicker.getMonth(), datePicker.getDayOfMonth());
dateTextView.setText(new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime()));
String f_name = foodTextView.getText().toString();
String c_name = companyTextView.getText().toString();
String d_date = dateTextView.getText().toString();
Log.e("HistoryActivity", f_name);
Log.e("HistoryActivity", c_name);
Log.e("HistoryActivity", d_date);
historyInquiry(f_name, c_name, d_date);
});
builder.show();
}
private void historyInquiry(String food_name, String company_name, String date) {
apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
Call<List<CowInfoData>> call = apiInterface.getHistory_cow(food_name, company_name, date);
call.enqueue(new Callback<List<CowInfoData>>() {
#Override
public void onResponse(Call<List<CowInfoData>> call, Response<List<CowInfoData>> response) {
cowInfoDataList = response.body();
list.addAll(cowInfoDataList);
}
#Override
public void onFailure(Call<List<CowInfoData>> call, Throwable t) {
Log.e("ErrorMessage", t.toString());
}
});
Call<List<RiceInfoData>> call2 = apiInterface.getHistory_rice(food_name, company_name, date);
call2.enqueue(new Callback<List<RiceInfoData>>() {
#Override
public void onResponse(Call<List<RiceInfoData>> call, Response<List<RiceInfoData>> response) {
riceInfoDataList = response.body();
list.addAll(riceInfoDataList);
}
#Override
public void onFailure(Call<List<RiceInfoData>> call, Throwable t) {
Log.e("ErrorMessage", t.toString());
}
});
Call<List<VegetableInfoData>> call3 = apiInterface.getHistory_vegetable(food_name, company_name, date);
call3.enqueue(new Callback<List<VegetableInfoData>>() {
#Override
public void onResponse(Call<List<VegetableInfoData>> call, Response<List<VegetableInfoData>> response) {
vegetableInfoDataList = response.body();
list.addAll(vegetableInfoDataList);
}
#Override
public void onFailure(Call<List<VegetableInfoData>> call, Throwable t) {
Log.e("ErrorMessage", t.toString());
}
});
historyAdapter = new HistoryAdapter(list, HistoryActivity.this);
historyRecyclerView.setAdapter(historyAdapter);
historyAdapter.notifyDataSetChanged();
}
}
It's Adapter.
public class HistoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List list;
private Context context;
public HistoryAdapter(List list, Context context) {
this.list = list;
this.context = context;
}
#Override
public int getItemViewType(int position) {
if(list.get(position) instanceof CowInfoData) {
return 0;
} else if(list.get(position) instanceof RiceInfoData) {
return 1;
}
return 2;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if(viewType == 0) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_history_cow, parent, false);
CowHistoryViewHolder holder = new CowHistoryViewHolder(view);
return holder;
} else if(viewType == 1) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_history_rice, parent, false);
RiceHistoryViewHolder holder = new RiceHistoryViewHolder(view);
return holder;
} else {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_history_vegetable, parent, false);
VegetableHistoryViewHolder holder = new VegetableHistoryViewHolder(view);
return holder;
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder viewHolder, int position) {
if(this.getItemViewType(position) == 0) {
CowInfoData cowInfoData = (CowInfoData)list.get(position);
CowHistoryViewHolder holder = (CowHistoryViewHolder) viewHolder;
holder.cowCategoryTextView.setText(cowInfoData.getCow_category());
holder.cowCompanyTextView.setText(cowInfoData.getCow_packing_company());
holder.cowTrackingNumTextView.setText(cowInfoData.getCow_tracking_num());
holder.cowGradeTextView.setText(cowInfoData.getCow_grade());
Log.e("HistoryAdapter", cowInfoData.getCow_tracking_num());
} else if(this.getItemViewType(position) == 1) {
RiceInfoData riceInfoData = (RiceInfoData)list.get(position);
RiceHistoryViewHolder holder = (RiceHistoryViewHolder) viewHolder;
holder.riceNameTextView.setText(riceInfoData.getRice_name());
holder.riceCompanyTextView.setText(riceInfoData.getRice_company());
holder.riceProduceTextView.setText(riceInfoData.getProduce_date());
Log.e("HistoryAdapter", riceInfoData.getRice_name());
} else if(this.getItemViewType(position) == 2) {
VegetableInfoData vegetableInfoData = (VegetableInfoData)list.get(position);
VegetableHistoryViewHolder holder = (VegetableHistoryViewHolder) viewHolder;
holder.vegetableNameTextView.setText(vegetableInfoData.getVegetable_name());
holder.vegetableCompanyTextView.setText(vegetableInfoData.getVegetable_company());
Log.e("HistoryAdapter", vegetableInfoData.getVegetable_name());
} else {
Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
}
}
#Override
public int getItemCount() {
Log.e("HistoryAdapter", String.valueOf(list.size()));
return list.size();
}
public static class CowHistoryViewHolder extends RecyclerView.ViewHolder {
TextView cowCategoryTextView, cowCompanyTextView, cowTrackingNumTextView, cowGradeTextView;
public CowHistoryViewHolder(#NonNull View itemView) {
super(itemView);
cowCategoryTextView = itemView.findViewById(R.id.text_cow_category);
cowCompanyTextView = itemView.findViewById(R.id.text_cow_company);
cowTrackingNumTextView = itemView.findViewById(R.id.text_cow_tracking_num);
cowGradeTextView = itemView.findViewById(R.id.text_cow_grade);
}
}
public static class RiceHistoryViewHolder extends RecyclerView.ViewHolder {
TextView riceNameTextView, riceCompanyTextView, riceProduceTextView;
public RiceHistoryViewHolder(#NonNull View itemView) {
super(itemView);
riceNameTextView = itemView.findViewById(R.id.text_rice_name);
riceCompanyTextView = itemView.findViewById(R.id.text_rice_company);
riceProduceTextView = itemView.findViewById(R.id.text_rice_produce);
}
}
public static class VegetableHistoryViewHolder extends RecyclerView.ViewHolder {
TextView vegetableNameTextView, vegetableCompanyTextView;
public VegetableHistoryViewHolder(#NonNull View itemView) {
super(itemView);
vegetableNameTextView = itemView.findViewById(R.id.text_vegetable_name);
vegetableCompanyTextView = itemView.findViewById(R.id.text_vegetable_company);
}
}
}
Plz Help me.
You are not calling notifyDataSetChanged(); after updating data
just add historyAdapter.notifyDataSetChanged(); after list.addAll(cowInfoDataList);
also
historyAdapter = new HistoryAdapter(list, HistoryActivity.this);
historyRecyclerView.setAdapter(historyAdapter);
These two lines should be executed before calling API. May be inside oncreate()
I never asked any question before but hope you'll get my point.
I am making a chat app in which I am using a RecyclerView to show messages. The problem is when I scroll the RecyclerView some of the items disappear from the top and the whole items messes up when I try to add a message it doesn't even scroll to bottom nor added in the ListView.
Here is my RecyclerView:
<android.support.v7.widget.RecyclerView
android:id="#+id/conversation_recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:layout_above="#id/typingConversationLayout"
android:layout_below="#id/topLayout_conversation_activity"
android:layout_marginBottom="-5dp"
android:paddingBottom="7dp" />
Initializing and setting the RecycerView:
linearLayoutManager = new LinearLayoutManager(this);
adapter = new ConversationRecyclerViewAdapter();
conversationRecyclerView.setAdapter(adapter);
conversationRecyclerView.setLayoutManager(linearLayoutManager);
linearLayoutManager.setStackFromEnd(true);
conversationRecyclerView.setHasFixedSize(true);
conversationRecyclerView.setNestedScrollingEnabled(false);
Here is my Adapter class:
private class ConversationRecyclerViewAdapter
extends RecyclerView.Adapter<ConversationRecyclerViewAdapter.ConversationViewHolder> {
#NonNull
#Override
public ConversationViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int i) {
Log.d(TAG, "onCreateViewHolder: Users Find started");
View conversationsView = LayoutInflater.from(parent.getContext()).inflate(
R.layout.layout_message_received, parent, false);
return new ConversationViewHolder(conversationsView);
}
#Override
public void onBindViewHolder(#NonNull final ConversationViewHolder holderConversation, int i) {
Log.d(TAG, "onBindViewHolder: Users Find started at position is " + i);
final int position = holderConversation.getAdapterPosition();
if (mOwnUser_1.get(position)) {
holderConversation.receivedMsgLayout.setVisibility(View.GONE);
holderConversation.sentProfileImg.setImageResource(mUserProfileImg_2.get(position));
holderConversation.sentMsg.setText(mUserText_3.get(position));
} else {
holderConversation.sentMsgLayout.setVisibility(View.GONE);
holderConversation.receivedProfileImg.setImageResource(mUserProfileImg_2.get(position));
holderConversation.receivedMsg.setText(mUserText_3.get(position));
}
Log.d(TAG, "onBindViewHolder: completed at " + position);
}
#Override
public int getItemCount() {
return mOwnUser_1.size();
}
public class ConversationViewHolder extends RecyclerView.ViewHolder {
RelativeLayout receivedMsgLayout, sentMsgLayout;
EmojiTextView receivedMsg, sentMsg;
CircleImageView receivedProfileImg, sentProfileImg;
public ConversationViewHolder(#NonNull View v) {
super(v);
receivedMsgLayout = v.findViewById(R.id.received_message_layout);
sentMsgLayout = v.findViewById(R.id.sent_message_layout);
receivedMsg = v.findViewById(R.id.received_message_text);
sentMsg = v.findViewById(R.id.sent_message_text);
receivedProfileImg = v.findViewById(R.id.received_message_user__profile_image);
sentProfileImg = v.findViewById(R.id.sent_message_user__profile_image);
}
}
}
Here I am adding data to ListView and displaying to the RecyclerView:
sendBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String msg = editText.getText().toString().trim();
if (TextUtils.isEmpty(msg)) {
editText.setError("Please add a message");
editText.requestFocus();
} else {
Log.d(TAG, "onClick: send Btn ADDED TEXT.. ");
mOwnUser_1.add(user);
mUserProfileImg_2.add(image);
mUserText_3.add(message);
editText.setText("");
editText.requestFocus();
adapter.notifyItemInserted(mOwnUser_1.size());
conversationRecyclerView.scrollToPosition(mOwnUser_1.size() - 1);
}
}
});
I don't know what i am doing wrong but it does not seem to work as i wanted.
Update Code:
The three listviews:
private ArrayList<Boolean> mOwnUser_1 = new ArrayList<>();
private ArrayList<Integer> mUserProfileImg_2 = new ArrayList<>();
private ArrayList<String> mUserText_3 = new ArrayList<>();
And the way of adding data to adapter:
mOwnUser_1.add(true);
mUserProfileImg_2.add(R.drawable.boy);
mUserText_3.add(edittext.getText().toString().trim());
adapter.notifyItemInserted(mOwnUser_1.size());
conversationRecyclerView.scrollToPosition(mOwnUser_1.size() - 1);
My Whole Conversation Activity Class:
public class ConversationActivity extends AppCompatActivity {
private static final String TAG = "ConversationActivity";
private EditText editText;
private LinearLayout linearLayout;
private LinearLayoutManager linearLayoutManager;
private ImageView sendBtn;
private ImageView emojiImage;
private View rootView;
private Boolean popUpShown = false;
private Boolean micShown = false;
private ImageView micBtn;
private RelativeLayout micLayout;
private RecyclerView conversationRecyclerView;
// Array Lists for Find USERS
private ArrayList<Boolean> mOwnUser_1 = new ArrayList<>();
private ArrayList<Integer> mUserProfileImg_2 = new ArrayList<>();
private ArrayList<String> mUserText_3 = new ArrayList<>();
private ConversationRecyclerViewAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate: started");
super.onCreate(savedInstanceState);
EmojiManager.install(new TwitterEmojiProvider());
setContentView(R.layout.activity_conversation);
editText = findViewById(R.id.conversationEditText);
linearLayout = findViewById(R.id.optionsOther);
emojiImage = findViewById(R.id.emojiIconOther);
rootView = findViewById(R.id.root_view_conversation);
micBtn = findViewById(R.id.microphoneBtn);
micLayout = findViewById(R.id.microphoneLayout);
conversationRecyclerView = findViewById(R.id.conversation_recyclerView);
sendBtn = findViewById(R.id.sendBtnConversation);
if (!(Build.VERSION.SDK_INT >= 21))
findViewById(R.id.typingConversationLayout).setBackgroundResource(R.drawable.edit_text_conversation_background_below_api);
sendBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String msg = editText.getText().toString().trim();
if (TextUtils.isEmpty(msg)) {
editText.setError("Please add a message");
editText.requestFocus();
} else {
Log.d(TAG, "onClick: send Btn ADDED TEXT.. ");
addData(true, R.drawable.boy0, msg);
}
}
});
initConversationArrayList();
}
private void addData(Boolean user, int image, String message) {
mOwnUser_1.add(user);
mUserProfileImg_2.add(image);
mUserText_3.add(message);
editText.setText("");
editText.requestFocus();
adapter.notifyItemInserted(mOwnUser_1.size());
conversationRecyclerView.scrollToPosition(mOwnUser_1.size() - 1);
}
private void initConversationArrayList() {
Log.d(TAG, "initConversationArrayList: created");
mOwnUser_1.add(true);
mUserProfileImg_2.add(R.drawable.boy0);
mUserText_3.add("Hello How are you?");
Log.d(TAG, "initConversationArrayList: completed");
initConversationRecyclerView();
}
private void initConversationRecyclerView() {
Log.d(TAG, "initConversationRecyclerView: started");
linearLayoutManager = new LinearLayoutManager(this);
adapter = new ConversationRecyclerViewAdapter();
conversationRecyclerView.setAdapter(adapter);
conversationRecyclerView.setLayoutManager(linearLayoutManager);
linearLayoutManager.setStackFromEnd(true);
conversationRecyclerView.setHasFixedSize(true);
conversationRecyclerView.setNestedScrollingEnabled(false);
Log.d(TAG, "initConversationRecyclerView: completed");
}
Currently I am also working on chat module, let me show you how am I doing this. I am going to show you in steps.
Step 1: make two separate layout for recyclerview items, one for message that has been sent from your side and one for message received from another side.
Step 2 : make two view holders to populate different layout according to your scenario, made in above step, like this:
public class ChatNewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Chat> chats;
public ChatNewAdapter(List<Chat> chats) {
this.chats = chats;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == 0) {
View viewSend = (View) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message_send, parent, false);
return new ViewHolderSend(viewSend);
} else {
View viewReceive = (View) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_message_received, parent, false);
return new ViewHolderReceive(viewReceive);
}
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case 0:
ViewHolderSend viewHolderSend = (ViewHolderSend) holder;
viewHolderSend.messageSend.setText(chats.get(position).getMessage());
break;
case 1:
ViewHolderReceive viewHolderReceive = (ViewHolderReceive) holder;
viewHolderReceive.messageReceived.setText(chats.get(position).getMessage());
break;
}
}
#Override
public int getItemCount() {
return chats.size();
}
#Override
public int getItemViewType(int position) {
if (chats != null && !chats.get(position).fromAdmin) {
return 0;
} else
return 1;
}
class ViewHolderSend extends RecyclerView.ViewHolder {
TextView messageSend;
public ViewHolderSend(View itemView) {
super(itemView);
messageSend = (TextView) itemView.findViewById(R.id.messageSend);
}
}
class ViewHolderReceive extends RecyclerView.ViewHolder {
TextView messageReceived;
public ViewHolderReceive(View itemView) {
super(itemView);
messageReceived = (TextView) itemView.findViewById(R.id.messageReceived);
}
}
public int addMessages(Chat chat) {
chats.add(chat);
notifyDataSetChanged();
return chats.size();
}
Step 3 : now in your activity:
public class Test extends AppCompatActivity {
RecyclerView chatList;
RecyclerView.LayoutManager mLayoutManager;
ChatNewAdapter adapter;
ImageView sendButton;
EditText messageEditText;
boolean keyboardUp = false;
boolean isRunning = false;
ArrayList<Chat> chats;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
isRunning = true;
setUpComponents();
}
public void setUpComponents() {
chatList = (RecyclerView) findViewById(R.id.chat_list);
chatList.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
chatList.setLayoutManager(mLayoutManager);
messageEditText = (EditText) findViewById(R.id.messageText);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
sendButton = (ImageView) findViewById(R.id.send);
adapter = new ChatNewAdapter(chats);
chatList.setAdapter(adapter);
chatList.scrollToPosition(chatList.getAdapter().getItemCount() - 1);
messageEditText.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (keyboardShown(messageEditText.getRootView())) {
Log.d("keyboard", "keyboard UP");
if (keyboardUp == false) {
if (chats.size() > 0)
chatList.smoothScrollToPosition(chats.size() + 1);
keyboardUp = true;
}
} else {
Log.d("keyboard", "keyboard Down");
keyboardUp = false;
}
}
});
sendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final String message = messageEditText.getText().toString().trim();
if (!message.equals("")) {
Chat chat = new Chat();
String name = message;
chat.setMessage(name);
messageEditText.setText("");
adapter.addMessages(chat);
chatList.scrollToPosition(chatList.getAdapter().getItemCount() - 1);
} else {
Log.d("sending message Error", "error fetching dates");
}
}
});
}
private boolean keyboardShown(View rootView) {
final int softKeyboardHeight = 100;
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
int heightDiff = rootView.getBottom() - r.bottom;
return heightDiff > softKeyboardHeight * dm.density;
}
And this is my model class, ignore #PrimaryKey and #Required annotation it just because I am using Realm for local DB. In your case you wont required these annotation.
public class Chat extends RealmObject {
#PrimaryKey
#Required
public Long id;
public boolean fromAdmin;
#Required
public String message;
public int type;
public boolean isRead;
public boolean isSent;
public Date date;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public boolean isFromAdmin() {
return fromAdmin;
}
public void setFromAdmin(boolean fromAdmin) {
this.fromAdmin = fromAdmin;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public boolean isRead() {
return isRead;
}
public void setRead(boolean read) {
isRead = read;
}
public boolean isSent() {
return isSent;
}
public void setSent(boolean sent) {
isSent = sent;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
I hope it will be helpful for you, you can ask further if you want to know anything else related to code.
RecyclerView as the name stands recycles the views. When binding data to a view, you need to ensure you set or reset all views that are touched in the adapter. Messups typically occur when there's data that is set only conditionally for some but not all items.
In particular:
if (mOwnUser_1.get(position)) {
holderConversation.receivedMsgLayout.setVisibility(View.GONE);
holderConversation.sentProfileImg.setImageResource(mUserProfileImg_2.get(position));
holderConversation.sentMsg.setText(mUserText_3.get(position));
} else {
holderConversation.sentMsgLayout.setVisibility(View.GONE);
holderConversation.receivedProfileImg.setImageResource(mUserProfileImg_2.get(position));
holderConversation.receivedMsg.setText(mUserText_3.get(position));
}
Both of these branches will need to reset the other layout back to visible.
Anyway with this kind of two-layout approach you are likely better off by having them as separate view types in your adapter. See How to create RecyclerView with multiple view type?
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");
I have successfully to get next page of post using Blogger's API, but i can't achieve the smooth scrolling of recyclerview, it look lagging.
I have tried using recyclerViewData.setNestedScrollingEnabled(false) and adapter.notifyDataSetChanged() but still doesn't work.
My point is How to achieve smooth of recyclerview. Any suggestion will be appreciate. thank is advance.
Here is my code
private void getData() {
showLoading(true);
final Call<ResponseBlogPost> postList = apiService.getListPost(GlobalVariable.APP_KEY);
postList.enqueue(new Callback<ResponseBlogPost>() {
#Override
public void onResponse(Call<ResponseBlogPost> call, Response<ResponseBlogPost> response) {
showLoading(false);
ResponseBlogPost responseBlogPost = response.body();
initDataView(responseBlogPost);
}
#Override
public void onFailure(Call<ResponseBlogPost> call, Throwable t) {
showLoading(false);
Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
private void initDataView(ResponseBlogPost listpost){
GlobalFunction.saveString(this,GlobalVariable.TOKEN_PAGINATION, listpost.getNextPageToken());
final String nextPageToken = GlobalFunction.getStrings(this, GlobalVariable.TOKEN_PAGINATION);
itemsList.addAll(listpost.getItems());
adapter = new MainAdapter(itemsList) {
#Override
public void load() {
if(nextPageToken==null){
return;
}
getNextListPost();
}
};
recyclerViewData.setAdapter(adapter);
recyclerViewData.setHasFixedSize(true);
staggeredGridLayoutManager = new StaggeredGridLayoutManager(2,1);
staggeredGridLayoutManager.setGapStrategy(0);
recyclerViewData.setLayoutManager(staggeredGridLayoutManager);
}
private void getNextListPost(){
showLoading(true);
final String nextPageToken = GlobalFunction.getStrings(this, GlobalVariable.TOKEN_PAGINATION);
Call<ResponseBlogPost> call = apiService.getNexPageListPost(GlobalVariable.APP_KEY,nextPageToken);
call.enqueue(new Callback<ResponseBlogPost>() {
#Override
public void onResponse(Call<ResponseBlogPost> call, Response<ResponseBlogPost> response) {
showLoading(false);
ResponseBlogPost responseModel = response.body();
if(nextPageToken!=null){
initDataView2(responseModel);
}else{
Toast.makeText(MainActivity.this, "tidak ada data lagi ya", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<ResponseBlogPost> call, Throwable t) {
showLoading(false);
Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
private void initDataView2(ResponseBlogPost listpost){
GlobalFunction.saveString(this,GlobalVariable.TOKEN_PAGINATION, listpost.getNextPageToken());
final String nextPageToken = GlobalFunction.getStrings(this, GlobalVariable.TOKEN_PAGINATION);
itemsList.addAll(listpost.getItems());
adapter = new MainAdapter(itemsList) {
#Override
public void load() {
if(nextPageToken!=null){
getNextListPost();
}
}
};
recyclerViewData.setAdapter(adapter);
recyclerViewData.setHasFixedSize(true);
staggeredGridLayoutManager = new StaggeredGridLayoutManager(2, 1);
staggeredGridLayoutManager.setGapStrategy(0);
recyclerViewData.setLayoutManager(staggeredGridLayoutManager);
}
My Adapter Code :
public abstract class MainAdapter extends RecyclerView.Adapter<MainAdapter.MainViewHolder>{
private List<BlogPostModel> responseBlogPost;
public MainAdapter(List<BlogPostModel> responseBlogPost) {
this.responseBlogPost = responseBlogPost;
}
public abstract void load();
#Override
public MainViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_main,parent,false);
return new MainViewHolder(view);
}
#Override
public void onBindViewHolder(final MainViewHolder holder, int position) {
final BlogPostModel model = responseBlogPost.get(position);
ArrayList<String> urlImage = pullLinks(model.getContent());
String firstImage = "";
for (int i = 0; i < urlImage.size(); i++) {
firstImage = urlImage.get(1);
GlideCustomLoading.setImageFromURL(holder.itemView.getContext(), urlImage.get(0)
,holder.avLoadingIndicatorView, holder.ivItemPost,holder.tvFailedLoadImage);
}
holder.tvTitleItemPost.setText(model.getTitle());
final String finalFirstImage = firstImage;
holder.llItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String id = String.valueOf(model.getId());
DetailPostActivity.start(holder.itemView.getContext(), id, finalFirstImage, model.getTitle(), model.getUrl());
}
});
if(position>=getItemCount()-1){
load();
}
}
#Override
public int getItemCount() {
return responseBlogPost.size();
}
public class MainViewHolder extends RecyclerView.ViewHolder{
CardView cardViewItemPost;
ImageView ivItemPost;
TextView tvTitleItemPost;
AVLoadingIndicatorView avLoadingIndicatorView;
TextView tvFailedLoadImage;
LinearLayout llItem;
public MainViewHolder(View itemView) {
super(itemView);
cardViewItemPost = itemView.findViewById(R.id.cardview_item_post);
ivItemPost = itemView.findViewById(R.id.iv_image_post);
tvTitleItemPost = itemView.findViewById(R.id.tv_title_post);
avLoadingIndicatorView = itemView.findViewById(R.id.avi_load);
tvFailedLoadImage = itemView.findViewById(R.id.tv_gagal_menampilkan_gambar);
llItem = itemView.findViewById(R.id.ll_item_post);
}
}
private ArrayList pullLinks(String html) {
ArrayList links = new ArrayList();
Elements srcs = Jsoup.parse(html).select("[src]"); //get All tags containing "src"
for (int i = 0; i < srcs.size(); i++) {
links.add(srcs.get(i).attr("abs:src")); // get links of selected tags
}
return links;
}
}
While I'm not familiar with Jsoup I'm reasonably confident that it's the source of your scroll lag.
You are calling the method pullLinks in your onBindViewHolder method which is called every time a new view is added to your RecyclerView. I'm assuming pullLinks does some pretty intensive work that takes some time to complete.
What you would be better off doing is to add all of the data to each item in your responseBlogPost List before loading it in to the adapter.