update data from intentservice on an activity - android

I have an activity with the following code and I am trying to update the data from IntentService by creating the instance of the class and calling the method to update but it's crashing with a null pointer exception at mAdapter. Is this the right way to pass data from IntentService to an activity?
COde:
public class MainActivity extends Activity {
RecyclerView rv;
SimpleStringRecyclerViewAdapter mAdapter;
public static final TypedValue mTypedValue = new TypedValue();
public static int mBackground;
public static List<String> mValues;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.cheesecake_homepage_fragment_cheese_list);
rv = (RecyclerView) findViewById(R.id.recyclerview);
setupRecyclerView(rv);
send_msg("");
}
public void setupRecyclerView(RecyclerView recyclerView) {
mAdapter = new SimpleStringRecyclerViewAdapter(getBaseContext(),
getRandomSublist(Cheeses.sCheeseStrings, 3));
recyclerView.setLayoutManager(new LinearLayoutManager(recyclerView.getContext()));
recyclerView.setAdapter(mAdapter);
}
private List<String> getRandomSublist(String[] array, int amount) {
ArrayList<String> list = new ArrayList<>(amount);
Random random = new Random();
while (list.size() < amount) {
list.add(array[random.nextInt(array.length)]);
}
return list;
}
public static class SimpleStringRecyclerViewAdapter
extends RecyclerView.Adapter<SimpleStringRecyclerViewAdapter.ViewHolder> {
public static class ViewHolder extends RecyclerView.ViewHolder {
public String mBoundString;
public final View mView;
public final ImageView mImageView;
public final TextView mTextView;
public ViewHolder(View view) {
super(view);
mView = view;
mImageView = (ImageView) view.findViewById(R.id.avatar);
mTextView = (TextView) view.findViewById(android.R.id.text1);
}
#Override
public String toString() {
return super.toString() + " '" + mTextView.getText();
}
}
public String getValueAt(int position) {
return mValues.get(position);
}
public SimpleStringRecyclerViewAdapter(Context context, List<String> items) {
context.getTheme().resolveAttribute(R.attr.selectableItemBackground, mTypedValue, true);
mBackground = mTypedValue.resourceId;
mValues = items;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.cheesecake_homepage_list_item, parent, false);
view.setBackgroundResource(mBackground);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.mBoundString = mValues.get(position);
holder.mTextView.setText(mValues.get(position));
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Context context = v.getContext();
/*Intent intent = new Intent(context, CheeseDetailActivity.class);
intent.putExtra(CheeseDetailActivity.EXTRA_NAME, holder.mBoundString);
context.startActivity(intent);*/
}
});
}
#Override
public int getItemCount() {
return mValues.size();
}
}
public void send_msg( String set_text){
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
List<String> uu = getRandomSublist(Cheeses.sCheeseStrings, 1);
mValues.addAll(uu);
mAdapter.notifyDataSetChanged();
}
});
}
}
In intent service:
MainActivity test = new MainActivity();
test.send_msg("");

You can not use MainActivity instance like that in your Intent service code.
There are multiple approach to update UI from service like, LocalBroadcastReceivers, Messengers, BoundedService etc.
You can find an example to update UI from service using LocalBroadcastManager here

update data from intentservice on an activity
By creating Object of class which is extending Activity or any other main application component is not right way for communication between components.
For with in process communication(as in your case want to send data from IntentService to Activity) use LocalBroadcastManager

Related

How can i get the all value of Recyclerview on Button click?

public class MainActivity extends Activity implements
GetDataContract.View,RecyclerItemClickListener {
private Presenter mPresenter;
RecyclerView recyclerView;
LinearLayoutManager linearLayoutManager;
CountryAdapter countryAdapter;
EditText etEnterName;
Button btAddItem;
List<CountryRes> allCountriesEditValue;
List<CountryRes> allCountriesData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getView();
}
private void getView() {
/*presentator */
mPresenter = new Presenter(this);
/*initiliaze of id*/
recyclerView = (RecyclerView) findViewById(R.id.recycler);
etEnterName = (EditText) findViewById(R.id.etEnterName);
btAddItem = (Button) findViewById(R.id.btAddItem);
linearLayoutManager = new LinearLayoutManager(this);
/*initiliaze the arraylist*/
allCountriesData=new ArrayList<>();
recyclerView.setLayoutManager(linearLayoutManager);
btAddItem.setOnClickListener(new AddButtonClick());
}
#Override
public void onGetDataFailure(String message) {
Log.d("Status", message);
}
#Override
public void onGetDataSuccess(String message, List<CountryRes>
allCountriesData) {
/*add the value mannulay*/
CountryRes countryRes = new CountryRes();
countryRes.setName(etEnterName.getText().toString());
allCountriesData.add(countryRes);
countryAdapter = new CountryAdapter(getApplicationContext(),
allCountriesData, (RecyclerItemClickListener) this);
recyclerView.setAdapter(countryAdapter);
/*set the data in the room*/
AppDataBase database = AppDataBase.getAppDatabase(this);
DataGenerator.with(database).generateCats(allCountriesData);
Logger.displayCatsInLog(database.catDao().loadAll());
countryAdapter.notifyDataSetChanged();
}
/*on item click*/
#Override
public void onDashBoardItemClick(String pos) {
Bundle bundle = new Bundle();
bundle.putString("TABVALUE", pos);
Intent intent = new Intent(getApplicationContext(),
DynamicTabsActivity.class);
intent.putExtras(bundle);
startActivity(intent);
}
private class AddButtonClick implements View.OnClickListener {
#Override
public void onClick(View view) {
mPresenter.getDataFromURL(getApplicationContext(), "");
}
}
}
class adapter
public class CountryAdapter extends
RecyclerView.Adapter<CountryAdapter.MyViewHolder> {
private Context context;
private List<CountryRes> list = new ArrayList<>();
private List<CountryRes> list_edit = new ArrayList<>();
private RecyclerItemClickListener onRecyclerItemClickListener;
public CountryAdapter(Context context, List<CountryRes> list,
RecyclerItemClickListener onRecyclerItemClickListener) {
this.context = context;
this.list = list;
this.onRecyclerItemClickListener = onRecyclerItemClickListener;
}
#Override
public CountryAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View layoutView;
layoutView =
LayoutInflater.from(parent.getContext()).inflate(R.layout.card_item, parent,
false);
return new FooterViewHolder(layoutView,
onRecyclerItemClickListener);
}
#Override
public void onBindViewHolder(CountryAdapter.MyViewHolder holder, int
position) {
holder.tvCountryName.setText(list.get(position).getName());
}
#Override
public int getItemCount() {
return list.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView tvCountryName;
LinearLayout llListItem;
public MyViewHolder(View itemView) {
super(itemView);
tvCountryName = (TextView)
itemView.findViewById(R.id.tv_country_name);
llListItem = (LinearLayout)
itemView.findViewById(R.id.llListItem);
}
}
private class FooterViewHolder extends MyViewHolder {
public FooterViewHolder(View layoutView, final
RecyclerItemClickListener onRecyclerItemClickListener) {
super(layoutView);
llListItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (onRecyclerItemClickListener != null) {
onRecyclerItemClickListener.onDashBoardItemClick(tvCountryName.getText().toS
tring());
}
}
});
}
}
}
Interface
public interface RecyclerItemClickListener {
void onDashBoardItemClick(String pos);
}
Case 1: Inside ViewHolder if you need to understand exactly position of clicked item you could call getAdapterPosition().
Case 2: You just need to receive all items of adapter. It is simple, make getter method which will return the items.
Case 3: Send info to activity, first make some specific event listener of your view inside ViewHolder, then event triggers (user clicks or other) and you call your interface method which you passed inside adapter, that was implemented in activity.
Tell me if you need an example, i will do it.
Try this one,
Button button= (Button) findViewById(R.id.your_button_id);
button.setOnClickListener( new OnClickListener() {
#Override
public void onClick(View v) {
//create new ArrayList.
//ArrayList<CountryRes> showList=new ArrayList<>;
//now, put all stored data of a list in this arraylist.
showList.addAll(allCountriesData);
}
});

accessing an adapter's data via another adapter

Is it all possible to access an adapter's data via another adapter?
I want to start an activity and pass data from an adapter to a fragment which is used in TabLayout as one of three fragments, I have two adapters and a button which is clicked to start an activity, its Java code is in my first adapter and I need to pass second adapter's data via second adapter itself
here is my codes:
my first adapter:
public class RecyclerViewDataAdapter extends RecyclerView.Adapter<RecyclerViewDataAdapter.ItemRowHolder>{
private ArrayList<SectionDataModel> dataList;
private Context mContext;
private RecyclerView.RecycledViewPool recycledViewPool;
private SnapHelper snapHelper;
public RecyclerViewDataAdapter(ArrayList<SectionDataModel> dataList, Context mContext) {
this.dataList = dataList;
this.mContext = mContext;
recycledViewPool = new RecyclerView.RecycledViewPool();
}
#Override
public ItemRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, null);
ItemRowHolder rowHolder = new ItemRowHolder(v);
snapHelper = new GravitySnapHelper(Gravity.START);
return rowHolder;
}
#Override
public void onBindViewHolder(ItemRowHolder holder, int position) {
ArrayList singleSectionItems = dataList.get(position).getAllItemInSection();
final String sectionName = dataList.get(position).getHeaderTitle();
holder.itemTitle.setText(sectionName);
SectionDataAdapter adapter = new SectionDataAdapter(singleSectionItems, mContext);
holder.recyclerView.setHasFixedSize(true);
holder.recyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.HORIZONTAL, false));
holder.recyclerView.setAdapter(adapter);
holder.recyclerView.setRecycledViewPool(recycledViewPool);
snapHelper.attachToRecyclerView(holder.recyclerView);
holder.btnMore.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//here i can start the activity but..(second adapter)
Toast.makeText(view.getContext(), sectionName, Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return (null != dataList ? dataList.size() : 0);
}
public class ItemRowHolder extends RecyclerView.ViewHolder {
protected ImageView mitemImage;
protected TextView mitemtext;
protected TextView itemTitle;
protected RecyclerView recyclerView;
protected Button btnMore;
public ItemRowHolder(View itemView) {
super(itemView);
this.mitemImage = itemView.findViewById(R.id.itemImage);
this.mitemtext = itemView.findViewById(R.id.tvTitle);
this.itemTitle = itemView.findViewById(R.id.itemTitle);
this.recyclerView = itemView.findViewById(R.id.recycler_view_list);
this.btnMore = itemView.findViewById(R.id.btnMore);
}
}
} '
and my second adapter:
import java.net.PortUnreachableException;
import java.util.ArrayList;
public class SectionDataAdapter extends RecyclerView.Adapter<SectionDataAdapter.SssingleItemRowHolder>{
private ArrayList<SingleItemModel> itemModels;
private Context mContext;
public SectionDataAdapter(ArrayList<SingleItemModel> itemModels, Context mContext) {
this.itemModels = itemModels;
this.mContext = mContext;
}
#Override
public SingleItemRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_single_card, null);
SingleItemRowHolder singleItemRowHolder = new SingleItemRowHolder(v);
return singleItemRowHolder;
}
#Override
public void onBindViewHolder(SingleItemRowHolder holder, int position) {
SingleItemModel itemModel = itemModels.get(position);
holder.tvTitle.setText(itemModel.getName());
holder.mitemImage.setImageResource(itemModel.getImage());
}
#Override
public int getItemCount() {
return (null != itemModels ? itemModels.size() : 0);
}
public class SingleItemRowHolder extends RecyclerView.ViewHolder {
protected TextView tvTitle;
protected ImageView mitemImage;
public SingleItemRowHolder(View itemView) {
super(itemView);
final Intent intent = new Intent(mContext,MainActivity.class);
this.mitemImage = itemView.findViewById(R.id.itemImage);
this.tvTitle = itemView.findViewById(R.id.tvTitle);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//... need to start the activity from here
Toast.makeText(view.getContext(), tvTitle.getText(), Toast.LENGTH_SHORT).show();
}
});
}
}
Like #MilaDroid said you simply need a getter that returns the another Adapter's ArrayList<SingleItemModel> but the problem you will face is that you need to have the same instance of the Adapter from the Activity in order to get the populated ArrayList<SingleItemModel>.
A good workaround is to used Bill Pugh's Singleton in the Adapter
public class Adapter {
private ArrayList<SingleItemModel> list;
private Adapter() {}
public static Adapter getInstance() {
return InstInit.INSTANCE;
}
// Don't forget to set the list (or NPE)
// because we can't argue with a Singleton
public void setList(ArrayList<SingleItemModel> list) {
this.list = list;
}
// You can now get the ArrayList
public ArrayList<SingleItemModel> getList() {
return list;
}
private static class InstInit {
private static final Adapter INSTANCE = new Adapter();
}
// Overrided RecyclerView.Adapter Methods
.................
}
Retrieving the ArrayList assuming that the following Adapters are Singleton
AdapterOne a1 = AdapterOne.getInstance();
AdapterTwo a2 = AdapterTwo.getInstance();
ArrayList<SingleItemModel> a1RetrievedList = a1.getList();
// You don't need to create a new instance
// creating a new instance doesn't make sense
// because you need to repopulate the list
// for the new instance.
ArrayList<SingleItemModel> a2RetrievedList = a2.getList();
// You can also retrieve from AdapterTwo

How to getting the current value when i clicked my recycler view

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private String[] mDatasetname;
private Integer[] mexp;
Context context;
public ToggleButton select;
Integer selectedcountint=0;
private Bitmap[] mpro;
private String[] mloc;
private String[] mobj;
private String[] mselected;
public ArrayList<String> nselected = new ArrayList<>();
public static class MyViewHolder extends RecyclerView.ViewHolder{
public CardView mCardView;
public TextView mTextView;
public TextView texp;
public Button pdf;
public ToggleButton select;
public ImageView pro;
public TextView loc;
public MyViewHolder(View v){
super(v);
mCardView = (CardView) v.findViewById(R.id.card_view);
mTextView = (TextView) v.findViewById(R.id.tv_text);
texp = (TextView) v.findViewById(R.id.setexp);
pdf = (Button) v.findViewById(R.id.moreinfo);
select = (ToggleButton) v.findViewById(R.id.select);
pro = (ImageView) v.findViewById(R.id.setpropic);
loc = (TextView) v.findViewById(R.id.setlocation);
}
}
public MyAdapter(String[] myDataset,Integer[] exp,Bitmap[] pro,String[] loc,String[] obj){
mDatasetname = myDataset;
mexp=exp;
mpro=pro;
mloc=loc;
mobj=obj;
}
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
context=parent.getContext();
View vs = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_item, parent, false);
MyViewHolder vh = new MyViewHolder(vs);
return vh;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position){
holder.mTextView.setText(mDatasetname[position]);
holder.texp.setText(String.valueOf(mexp[position])+" yrs");
holder.pro.setImageBitmap(mpro[position]);
holder.loc.setText(mloc[position]);
holder.select.setText("rejected");
holder.pdf.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent=new Intent();
intent = new Intent(context, PdfViewer.class);
intent.putExtra("obj",mobj[position]);
context.startActivity(intent);
}
});
holder.select.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked==true) {
holder.select.setChecked(true);
holder.select.setText("selected");
nselected.remove(mobj[position]+",rejected");
nselected.add(mobj[position]+",selected");
Log.d("dei", String.valueOf(nselected));
selectedcountint=selectedcountint+1;
Intent intent = new Intent("custom-message");
// intent.putExtra("quantity",Integer.parseInt(quantity.getText().toString()));
Bundle args = new Bundle();
args.putSerializable("ARRAYLIST",(Serializable)nselected);
intent.putExtra("BUNDLE",args);
intent.putExtra("totalval",selectedcountint);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
} else {
holder.select.setChecked(false);
holder.select.setText("rejected");
nselected.remove(mobj[position]+",selected");
nselected.add(mobj[position]+",rejected");
Log.d("dei", String.valueOf(nselected));
selectedcountint=selectedcountint-1;
Intent intent = new Intent("custom-message");
// intent.putExtra("quantity",Integer.parseInt(quantity.getText().toString()));
Bundle args = new Bundle();
args.putSerializable("ARRAYLIST",(Serializable)nselected);
intent.putExtra("BUNDLE",args);
intent.putExtra("totalval",selectedcountint);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
}
});
}
#Override
public int getItemCount() { return mDatasetname.length; }
}
I have a recycler view in my app. I am having a problem. There is an item so that when I click on the item a the funtion in the click b is executed. It would be very great when you clean up the below code for me because I am new to programming, so that I won't be able to solve the problem.
if(getAdapterPosition() != RecyclerView.NO_POSITION) {
...
mobj[getAdapterPosition()]
...
}
It's better if you set your data and listeners in the ViewHolder. You should create a method in your ViewHolder class and pass there item from your list as a parameter. In this method you copy all your code for setting text and listeners. Then in onBindViewHolder you call this method.
First create a class that will be our Adapter item (you should change the names of the fields because I don't know what should they represent, this is just an example):
class AdapterItem {
private String firstString;
private Integer integerValue;
private Bitmap bitmap;
private String secondString;
private String thirdString;
// create also getters, setters for fields
}
Your adapters constructor will look something like this:
public MyAdapter(ArrayList<AdapterItem> data){
this.data = data;
}
And the onBindViewHolder method:
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position){
holder.bind(data[position]);
}
In the ViewHolder class:
void bind(AdapterItem item) {
mTextView.setText(item.getFirstString());
pdf.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, PdfViewer.class);
intent.putExtra("obj", item.getThirdString());
v.getContext().startActivity(intent);
}
});
}
As correctly pointed out by #andrei The code to get the correct string from the obj[] array should be as shown:
public MyAdapter(Context context, String[] myDataset,Integer[] exp,Bitmap[] pro,String[] loc,String[] obj){
mContext = context; // make mContext as a variable like others
mDatasetname = myDataset;
mexp=exp;
mpro=pro;
mloc=loc;
mobj=obj;
}
holder.pdf.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent=new Intent();
intent = new Intent(context, PdfViewer.class);
intent.putExtra("obj",mobj[holder.getAdapterPosition()]);
mContext.startActivity(intent);
}
});
And similarly replace all occurrences of position with holder.getAdapterPosition() because holder.getAdapterPosition() will always give you the updated position for an item of recycler view in your code as if you update or delete items without using notifyDataSetChanged() method then the onBindViewHolder will not be called again hence the position will become inconsistent. For detailed information you can refer to this answer.
public class MyAdapter extends RecyclerView.Adapter {
private String[] mDatasetname;
private Integer[] mexp;
private Context context;
public ToggleButton select;
Integer selectedcountint=0;
private Bitmap[] mpro;
private String[] mloc;
private String[] mobj;
public Button pdf;Context m;private String[] mselected;
public ArrayList<String> nselected = new ArrayList<>();
public static class MyViewHolder extends RecyclerView.ViewHolder{
public CardView mCardView;
public TextView mTextView;
public TextView texp;
public Button pdf;
public ToggleButton select;
public ImageView pro;
public MainActivity activity;
public Context ipaset;
public TextView loc;
public View layout;
View forresumeview;
String forresume;
private RecyclerView.ViewHolder s;
public MyViewHolder(final View v) {
super(v);
mCardView = (CardView) v.findViewById(R.id.card_view);
mTextView = (TextView) v.findViewById(R.id.tv_text);
texp = (TextView) v.findViewById(R.id.setexp);
pdf = (Button) v.findViewById(R.id.moreinfo);
select = (ToggleButton) v.findViewById(R.id.select);
pro = (ImageView) v.findViewById(R.id.setpropic);
loc = (TextView) v.findViewById(R.id.setlocation);
forresumeview=v;
}
void bind(String name, Integer exp, String location, final Bitmap image, final String obj ){
mTextView.setText(name);
texp.setText(String.valueOf(exp) + " yrs");
pro.setImageBitmap(image);
loc.setText(location);
}
public void doonce(final String s){
pdf.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View vs) {
Intent intent = new Intent(forresumeview.getContext(), PdfViewer.class);
intent.putExtra("obj", s);
forresumeview.getContext().startActivity(intent);
// Log.d("sdasd", obj);
}
});
}
}
public MyAdapter(String[] myDataset,Integer[] exp,Bitmap[] pro,String[] loc,String[] obj){
mDatasetname = myDataset;
mexp=exp;
mpro=pro;
mloc=loc;
mobj=obj;
}
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
context=parent.getContext();
View vs = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_item, parent, false);
MyViewHolder vh = new MyViewHolder(vs);
return vh;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position){
holder.bind(mDatasetname[position],mexp[position],mloc[position],mpro[position],mobj[position]);
holder.doonce(mobj[position]);
}
#Override
public int getItemCount() { return mDatasetname.length; }
}
this is the answer ,,,, it works i tried it !!!! Happy coding ......

How to render render JSON data using retrofit and recylerview in android studio

I am trying use retrofit and recyclerview to display from a web app. I have the following models:
Main Activities
public class ProfileActivity extends AppCompatActivity {
private SalesAdapter mAdapter;
private RecyclerView mRecyclerView;
private SaleService mService;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView(R.layout.activity_profile );
mService = ApiUtils.getSaleService();
mRecyclerView = (RecyclerView) findViewById(R.id.rvItems);
mAdapter = new SalesAdapter(this, new ArrayList<Sale>(0), new SalesAdapter.ItemListener() {
#Override
public void onPostClick(long id) {
}
});
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setHasFixedSize(true);
RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
mRecyclerView.addItemDecoration(itemDecoration);
loadAnswers();
}
public void loadAnswers() {
mService.getSales().enqueue(new Callback<List<Sale>>() {
#Override
public void onResponse(Call<List<Sale>> call, Response<List<Sale>> response) {
if(response.isSuccessful()) {
mAdapter.UpdateSales(response.body());
} else {
int statuscode = response.code();
}
}
#Override
public void onFailure(Call<List<Sale>> call, Throwable t) {
}
});
}
}
Recyclerview Adapter
public class SalesAdapter extends RecyclerView.Adapter<SalesAdapter.ViewHolder>{
private Context mContext;
private List<Sale> mSales;
private ItemListener mItemListener;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public TextView tvLocaleName;
ItemListener mItemListener;
public ViewHolder(View itemView, ItemListener itemListener) {
super(itemView);
tvLocaleName = (TextView) itemView.findViewById(android.R.id.text1);
this.mItemListener = itemListener;
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
Sale sale = getSales(getAdapterPosition());
this.mItemListener.onPostClick(sale.getId());
notifyDataSetChanged();
}
}
public SalesAdapter(Context mContext, List<Sale> mSales, ItemListener mItemListener) {
this.mContext = mContext;
this.mSales = mSales;
this.mItemListener = mItemListener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(android.R.layout.simple_list_item_1, parent, false);
return new ViewHolder(view, this.mItemListener);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Sale sale = mSales.get(position);
TextView textView = holder.tvLocaleName;
textView.setText(sale.getLocaleName());
}
#Override
public int getItemCount() {
return mSales.size();
}
public void UpdateSales(List<Sale> sales) {
mSales = sales;
}
private Sale getSales(int position) {
return mSales.get(position);
}
public interface ItemListener {
void onPostClick(long id);
}
}
from the image you can see that i am able to get back the data, but how do I display in it the recyclerview? where am i going wrong with code?
Add a notifyDataSetChanged() call to your adapter after you refresh the list.
Your method should look like:
public void UpdateSales(List<Sale> sales) {
mSales = sales;
notifyDataSetChanged();
}
Check out this link to learn more about this method.

Update and control multiple CountDownTimer in RecyclerView (pause, resume, delete)

I've implemented to my Android app multiple countdown timers with Service.
CountDownTimer is running with service, thus data to fragment is being passed with BroadcastReceiver.
I would like to add each timer as a separate item to the RecyclerView in the fragment and be able to update it as timer is ticking and also to control it - pause, resume, add 1 min and delete.
At the moment the problem is that each second that timer is running, new item is added to RecyclerView and I'm not able to control it - pause, resume and ect.
Service Class:
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(Constants.ACTION.START_FOREGROUND_ACTION)){
HandlerThread thread = new HandlerThread("ServiceStartArguments",
android.os.Process.THREAD_PRIORITY_BACKGROUND);
thread.setName(nameOfFood);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
#Override
public void handleMessage(Message msg) {
// Normally we would do some work here, like download a file.
Thread.currentThread().setName(nameOfFood);
try {
showCountDownTimer(enteredTimeFormatted);
} catch (Exception e) {
// Restore interrupt status.
Thread.currentThread().interrupt();
}
stopSelf(msg.arg1);
}
private void showCountDownTimer(long number) {
String normalStartTime = String.format(
"%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(number),
TimeUnit.MILLISECONDS.toMinutes(number) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(number)),
TimeUnit.MILLISECONDS.toSeconds(number) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(number)));
Intent timerStartInfoIntent = new Intent(TIMER_START_INFO);
timerStartInfoIntent.putExtra("VALUE", normalStartTime);
timerStartInfoIntent.putExtra("NAME_FOOD", nameOfFood);
LocalBroadcastManager.getInstance(NotificationService.this).sendBroadcast(timerStartInfoIntent);
CountDownTimer timer = new CountDownTimer(number, 1000) {
#Override
public void onTick(long millisUntilFinished) {
timeLeft = millisUntilFinished;
counter = millisUntilFinished / 1000;
normalTime = String.format(
"%02d:%02d:%02d",
TimeUnit.MILLISECONDS.toHours(timeLeft),
TimeUnit.MILLISECONDS.toMinutes(timeLeft) -
TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(timeLeft)),
TimeUnit.MILLISECONDS.toSeconds(timeLeft) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(timeLeft)));
Intent timerInfoIntent = new Intent(TIME_INFO);
timerInfoIntent.putExtra("VALUE", normalTime);
timerInfoIntent.putExtra("NAME_FOOD", nameOfFood);
LocalBroadcastManager.getInstance(NotificationService.this).sendBroadcast(timerInfoIntent);
}
#Override
public void onFinish() {
counter = 0;
Intent timerFinishInfoIntent = new Intent(TIMER_FINISH_INFO);
LocalBroadcastManager.getInstance(NotificationService.this).sendBroadcast(timerFinishInfoIntent);
}
};
timer.start();
}
Adapter Class:
public class TimerRecyclerViewAdapter extends RecyclerView.Adapter<TimerRecyclerViewAdapter.MyViewHolder> {
final private Context mContext;
public List<ModelTimer> mModelTimerList;
private final List<MyViewHolder> listHolder;
public TimerRecyclerViewAdapter(List<ModelTimer> modelTimerList, Context context) {
super();
this.mContext = context;
this.mModelTimerList = modelTimerList;
listHolder = new ArrayList<>();
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final TextView nameTextView;
public final TextView timerTextView;
public final Button pauseBtn;
public final Button addMinBtn;
public final Button deleteBtn;
ModelTimer mModelTimer;
public MyViewHolder(View itemView) {
super(itemView);
nameTextView = (TextView) itemView.findViewById(R.id.active_timer_name);
timerTextView = (TextView) itemView.findViewById(R.id.active_timer_timeLeft);
pauseBtn = (Button) itemView.findViewById(R.id.active_timer_btn_pause);
pauseBtn.setOnClickListener(this);
addMinBtn = (Button) itemView.findViewById(R.id.active_timer_btn_addMin);
addMinBtn.setOnClickListener(this);
deleteBtn = (Button) itemView.findViewById(R.id.active_timer_btn_delete);
deleteBtn.setOnClickListener(this);
}
public void setData (ModelTimer modelTimer){
this.mModelTimer = modelTimer;
timerTextView.setText(modelTimer.expirationTime);
nameTextView.setText(modelTimer.name);
}
#Override
public void onClick(View v) {
// TODO
}
}
#Override
public TimerRecyclerViewAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (parent instanceof RecyclerView) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_active_timer,
parent,
false);
v.setFocusable(true);
return new MyViewHolder(v);
} else {
throw new RuntimeException("No bound to RecyclerViewSelection");
}
}
#Override
public void onBindViewHolder(TimerRecyclerViewAdapter.MyViewHolder holder, int position) {
holder.setData(mModelTimerList.get(position));
synchronized (listHolder){
listHolder.add(holder);
}
}
#Override
public int getItemCount() {
return mModelTimerList.size();
}
Here I tried to create a method that will be upgrading each second a timer on specific position instead of adding new item to RecyclerView each time that timer is ticking.
public void swap(List<ModelTimer> modelTimerList){
mModelTimerList.clear();
mModelTimerList.addAll(modelTimerList);
notifyItemChanged(???);
}
public void delete() {
mModelTimerList.clear();
notifyDataSetChanged();
}
}
Fragment with RecyclerView:
public class ActiveTimersFragment extends Fragment {
private RecyclerView mRecyclerView;
private TimerRecyclerViewAdapter mAdapter;
private ArrayList<ModelTimer> listOfTimers;
private TimerStatusReceiver mTimerStatusReceiver;
private static final String ARG_SECTION_NUMBER = "section_number";
public ActiveTimersFragment() {
}
public static ActiveTimersFragment newInstance(int sectionNumber) {
ActiveTimersFragment activeTimersFragment = new ActiveTimersFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
activeTimersFragment.setArguments(args);
return activeTimersFragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_active_timers, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.fragment_active_timers_recycler_view);
mTimerStatusReceiver = new TimerStatusReceiver();
listOfTimers = new ArrayList<>();
return view;
}
#Override
public void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
mTimerStatusReceiver, new IntentFilter(NotificationService.TIME_INFO));
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
mTimerStatusReceiver, new IntentFilter(NotificationService.TIMER_START_INFO));
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
mTimerStatusReceiver, new IntentFilter(NotificationService.TIMER_FINISH_INFO));
}
#Override
public void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(mTimerStatusReceiver);
}
private class TimerStatusReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null && intent.getAction().equals(NotificationService.TIME_INFO)) {
ModelTimer modelTimer = new ModelTimer();
if (intent.hasExtra("VALUE")) {
modelTimer.setexpirationTime(intent.getStringExtra("VALUE"));
}
if (intent.hasExtra("NAME_FOOD")) {
modelTimer.setName(intent.getStringExtra("NAME_FOOD"));
}
listOfTimers.add(modelTimer);
mAdapter = new TimerRecyclerViewAdapter(listOfTimers, getActivity());
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
// Not working
// mAdapter.swap(listOfTimers);
mRecyclerView.setAdapter(mAdapter);
}
if (intent != null && intent.getAction().equals(NotificationService.TIMER_FINISH_INFO)) {
mAdapter.delete();
}
}
}
}
Your whole implementation of recyclerview adapter is wrong. In onBindViewHolder() you are adding new item. onBindViewHolder is called when RecyclerView tries to show new item. So it keeps on iterating, if you add new item in onBindViewHolder. Also, you should use the onBindViewHolder to set the views values in ViewHolder class. Check the whole adapter implementation.
public class TimerRecyclerViewAdapter extends RecyclerView.Adapter<TimerRecyclerViewAdapter.MyViewHolder> {
final private Context mContext;
public List<ModelTimer> mModelTimerList;
public TimerRecyclerViewAdapter(List<ModelTimer> modelTimerList, Context context) {
super();
this.mContext = context;
this.mModelTimerList = modelTimerList;
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final TextView nameTextView;
public final TextView timerTextView;
public final Button pauseBtn;
public final Button addMinBtn;
public final Button deleteBtn;
public MyViewHolder(View itemView) {
super(itemView);
nameTextView = (TextView) itemView.findViewById(R.id.active_timer_name);
timerTextView = (TextView) itemView.findViewById(R.id.active_timer_timeLeft);
pauseBtn = (Button) itemView.findViewById(R.id.active_timer_btn_pause);
pauseBtn.setOnClickListener(this);
addMinBtn = (Button) itemView.findViewById(R.id.active_timer_btn_addMin);
addMinBtn.setOnClickListener(this);
deleteBtn = (Button) itemView.findViewById(R.id.active_timer_btn_delete);
deleteBtn.setOnClickListener(this);
}
#Override
public void onClick(View v) {
// TODO
}
}
#Override
public TimerRecyclerViewAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (parent instanceof RecyclerView) {
View v = LayoutInflater.from(parent.getContext()).inflate(
R.layout.item_active_timer,
parent,
false);
v.setFocusable(true);
return new MyViewHolder(v);
} else {
throw new RuntimeException("No bound to RecyclerViewSelection");
}
}
#Override
public void onBindViewHolder(TimerRecyclerViewAdapter.MyViewHolder holder, int position) {
ModelTimer modelTimer=mModelTimerList.get(position);
holder.timerTextView.setText(modelTimer.expirationTime);
holder.nameTextView.setText(modelTimer.name);
}
#Override
public int getItemCount() {
return mModelTimerList.size();
}

Categories

Resources