I learn Dependency Injection using Dagger2 in my android code, I dont have any trouble using it until I try to inject the presenter in my CustomAdapter for ListView, it always return Null Value. The purpose is I want to execute the Presenter function when someone click the ListView Item. This is my CustomAdapter Looks like :
public class CustomAdapter extends BaseAdapter {
ArrayList<String> contactNameList, listGroup;
Context context;
ArrayList<Bitmap> contactImages;
ArrayList<Integer> listContactId;
private static LayoutInflater inflater=null;
#Inject
DetailScreenPresenter detailScreenPresenter;
public CustomAdapter(MainActivity mainActivity, ArrayList<String> contactNameList, ArrayList<Bitmap> contactImages, ArrayList<String> listGroup, ArrayList<Integer> listContactId)
{
this.contactNameList = contactNameList;
context = mainActivity;
this.contactImages = contactImages;
this.listGroup = listGroup;
this.listContactId = listContactId;
inflater = ( LayoutInflater )context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return contactNameList.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
public static class Holder
{
public Holder(View view,Context context)
{
ButterKnife.bind(this,view);
}
#BindView(R.id.txtName)
TextView tvName;
#BindView(R.id.txtGroup)
TextView tvGroup;
#BindView(R.id.imageProfile)
ImageView img;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View rowView;
rowView = inflater.inflate(R.layout.contact_list, null);
Holder holder=new Holder(rowView, context);
holder.tvName.setText(contactNameList.get(position));
holder.img.setImageBitmap(contactImages.get(position));
holder.tvGroup.setText(listGroup.get(position));
rowView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
detailScreenPresenter.loadDetail(listContactId.get(position));
}
});
return rowView;
}
}
and this is the MainActivity that trigger the CustomAdapter
public class MainActivity extends AppCompatActivity implements MainScreenContact.View {
#BindView(R.id.listContact)
ListView listView;
ArrayList<String> listName;
ArrayList<Bitmap> listImage;
ArrayList<String> listGroup;
ArrayList<Integer> listContactId;
HashMap<Integer, Bitmap> tempImageArray;
String[] letter={"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
#Inject
MainScreenPresenter mainPresenter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
listName = new ArrayList<>();
listImage = new ArrayList<>();
tempImageArray = new HashMap<>();
listGroup = new ArrayList<>();
listContactId = new ArrayList<>();
DaggerMainScreenComponent.builder()
.netComponent(((App) getApplicationContext()).getNetComponent())
.mainScreenModule(new MainScreenModule(this, new ContactDatabaseHelper(this)))
.build().inject(this);
mainPresenter.loadPost();
}
#Override
public void showPosts(List<Post> posts) {
Collections.sort(posts, new Comparator<Post>() {
#Override
public int compare(Post post1, Post post2) {
String name1=post1.getFirstName()+" "+post1.getLastName();
String name2=post2.getFirstName()+" "+post2.getLastName();
return name1.compareToIgnoreCase(name2);
}
});
int indexGroup=0;
for (int i = 0; i < posts.size(); i++) {
if(posts.get(i).getProfilePic().contains("http"))
mainPresenter.loadImage(posts.get(i).getProfilePic(), i);
else
mainPresenter.loadImage("http://example.com", i);
if(Arrays.binarySearch(letter,Character.toString(posts.get(i).getFirstName().charAt(0)).toUpperCase())==-1)
{
if(listGroup.size()==0)
listGroup.add("*");
else
listGroup.add(" ");
}
else
{
if(!listGroup.get(indexGroup).equalsIgnoreCase(Character.toString(posts.get(i).getFirstName().charAt(0)))) {
listGroup.add(Character.toString(posts.get(i).getFirstName().charAt(0)).toUpperCase());
indexGroup = i;
}
else
listGroup.add(" ");
}
listContactId.add(i, posts.get(i).getId());
listName.add(i, posts.get(i).getFirstName() + " " + posts.get(i).getLastName());
}
}
#Override
public void showError(String message) {
Toast.makeText(getApplicationContext(), "Error" + message, Toast.LENGTH_LONG).show();
}
#Override
public void showComplete() {
Toast.makeText(getApplicationContext(), "Complete", Toast.LENGTH_LONG).show();
}
#Override
public void setImageProfile(Bitmap profileBmp, int x) {
tempImageArray.put(x, profileBmp);
if(tempImageArray.size()==listName.size())
{
SortedSet<Integer> keys = new TreeSet<Integer>(tempImageArray.keySet());
for(Integer key : keys)
{
listImage.add(tempImageArray.get(key));
}
listView.setAdapter(new CustomAdapter(this, listName, listImage, listGroup, listContactId));
}
}
}
Please help how to inject the DetailScreenPresenter presenter.
Thanks alot
In general, in order to perform injection into any Object, you should explicitly call <some_dagger_component>.inject(<target_object>).
In your case, you could do it this way:
CustomAdapter adapter = new CustomAdapter(this, listName, listImage, listGroup, listContactId);
DaggerMainScreenComponent.builder()
.netComponent(((App) getApplicationContext()).getNetComponent())
.mainScreenModule(new MainScreenModule(this, new ContactDatabaseHelper(this)))
.build().inject(adapter);
listView.setAdapter(adapter);
However, what you're trying to do is an abuse of dependency injection framework - you should not perform injection into adapter, but simply pass the required objects to adapter's constructor.
In this post you can find additional information about dependency injection in Android.
Related
Here I'm trying to make a quiz application without using databases (requirement). Each question has 4 options.
I had made a class for Questions. Now, in the activity in which I want to show my data, I'm unable to get method to fetch the data from the QuestionModelClass.
I had made 2D Array but it gets more complicated to get it. Is there any way to bind 3 of the classes (QuestionModelClass, Adapter class, and Activity class)?
public class QuestionsModelClass {
private String sQuestion;
private String sRightAnswer;
private List<String> sOptions;
QuestionsModelClass(){
sQuestion = null;
sRightAnswer = null;
sOptions = null;
}
public QuestionsModelClass(String sQuestion, String sRightAnswer, List<String> sOptions) {
this.sQuestion = sQuestion;
this.sRightAnswer = sRightAnswer;
this.sOptions = sOptions;
}
public String getsQuestion() {
return sQuestion;
}
public void setsQuestion(String sQuestion) {
this.sQuestion = sQuestion;
}
public String getsRightAnswer() {
return sRightAnswer;
}
public void setsRightAnswer(String sRightAnswer) {
this.sRightAnswer = sRightAnswer;
}
public List<String> getsOptions() {
return sOptions;
}
public void setsOptions(List<String> sOptions) {
this.sOptions = sOptions;
}
}
And my Adapter Class
public class QuizAdapter extends BaseAdapter {
private Context context;
private List<QuestionsModelClass> questionClassList;
private String[][] options;
private LayoutInflater inflater;
private QuizAdapter(Context c, List<QuestionsModelClass> l){
this.context= c;
this.questionClassList = l;
inflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
return questionClassList.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView = inflater.inflate(R.layout.questionpattern, parent,false);
QuestionsModelClass questions = questionClassList.get(position);
TextView quesText= convertView.findViewById(R.id.questionTextView);
RadioButton radioButtonA = convertView.findViewById(R.id.optionA);
RadioButton radioButtonB = convertView.findViewById(R.id.optionB);
RadioButton radioButtonC = convertView.findViewById(R.id.optionC);
RadioButton radioButtonD = convertView.findViewById(R.id.optionD);
return convertView;
}
And this is the Activity class in which I am trying to implement all the functions
public class QuizActivity extends Activity {
final Context context= this;
private List<QuestionsModelClass> classObject;
Button okayButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_quiz);
String[] question= new String[]{"Q1. ABDE", "Q2. ADDASD"};
String[][] op;
String[] right = new String[]{"abc","def"};
classObject = new ArrayList<>();
op= new String[][]{
{"a1", "2", "3", "4"},
{"b1","b2","b3","b4"}};
final Dialog dialog = new Dialog(context);
dialog.setContentView(R.layout.customdialoguebox);
dialog.show();
okayButton = (Button) dialog.findViewById(R.id.okayButton);
okayButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(QuizActivity.this,"Good Luck!", Toast.LENGTH_SHORT).show();
dialog.cancel();
}
});
}
I have two ArrayLists from which I am trying to insert data into separate static ArrayList in another class and display in RecyclerView, but the recycler is not getting populated though the same was being done with a dummy ArrayList.Please help me with this problem.
My Class where I am inserting data from phoneContactNos and phoneContactName in two separate ArrayList: Common.selectedContactNos and Common.selectedContactName.
public void displayMatchedContacts()
{
try {
for (int i = 1; i < phoneContactNos.size(); i++) {
if (phoneContactNos.contains(registeredContactNos.get(i))) {
if (registeredContactNos.get(i) != null) {
try {
indexOfRegNumber = phoneContactNos.indexOf(registeredContactNos.get(i));
//Common.indexPosition_contacts=indexOfRegNumber;
Toast.makeText(this, "index" + String.valueOf(indexOfRegNumber), Toast.LENGTH_LONG).show();
if ((phoneContactNos.get(indexOfRegNumber) != null) &&(phoneContactName.get(indexOfRegNumber) != null)) {
//String regName="";
//String regContact="";
Common.selectedContactNos.add(phoneContactNos.get(indexOfRegNumber));
//Toast.makeText(this,selectedContactNos.get(i).toString(),Toast.LENGTH_SHORT).show();
//Toast.makeText(this,phoneContactNos.get(indexOfRegNumber).toString(),Toast.LENGTH_SHORT).show();
Common.selectedContactName.add(phoneContactName.get(indexOfRegNumber));
//Toast.makeText(this,selectedContactName.get(i).toString(),Toast.LENGTH_SHORT).show();
//Toast.makeText(this, phoneContactName.get(indexOfRegNumber).toString(), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "null index no", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Log.i("Contacts display error", e.getLocalizedMessage());
e.printStackTrace();
}
}
}
}
}catch (Exception e)
{
Log.i("Contacts error in loop", e.getLocalizedMessage());
e.printStackTrace();
}
}
My Common class
public final class Common {
public static ArrayList<String> selectedContactNos=new ArrayList<>();
public static ArrayList<String> selectedContactName=new ArrayList<>();
public static String fcmId="";
public static int position;
public static String contacts_list="";
public static int indexPosition_contacts;
}
My RecyclerView populating code
public void populateList() {
Log.i("Populate List","Entered");
LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this);
recyclerView_contacts.setLayoutManager(mLinearLayoutManager);
displayRecyclerAdapter = new DisplayRecyclerAdapter(this);
recyclerView_contacts.setAdapter(displayRecyclerAdapter);
}
My Adapter Class
public class DisplayRecyclerAdapter extends RecyclerView.Adapter<DisplayRecyclerAdapter.displayViewHolder> {
private LayoutInflater mInflater;
private Context context;
Fragment fragment;
FragmentTransaction ft;
FrameLayout container;
public DisplayContacts displayContacts;
public DisplayRecyclerAdapter(Context context) {
this.mInflater = LayoutInflater.from(context);
this.context = context;
ft = ((AppCompatActivity) context).getSupportFragmentManager().beginTransaction();
//displayContacts = new DisplayContacts();
}
#Override
public displayViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.contacts_row, parent, false);
displayViewHolder holder = new displayViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(displayViewHolder holder, int position) {
holder.setData(position);
//Common.position = position;
holder.setListeners();
//for(int i=0;i<((DisplayContacts)context).selectedContactName.size();i++)
for(int i=0;i<Common.selectedContactName.size();i++)
{
//String contactName=((DisplayContacts)context).selectedContactName.get(i);
String contactName=Common.selectedContactName.get(i);
//String contactNumber=((DisplayContacts)context).selectedContactNos.get(i);
String contactNumber=Common.selectedContactNos.get(i);
Toast.makeText(context,contactName+","+contactNumber,Toast.LENGTH_SHORT).show();
}
}
class displayViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
int position;
//ImageView productSearchImg;
TextView name_contactList;
Button call_contact;
public displayViewHolder(View itemView) {
super(itemView);
name_contactList = (TextView) itemView.findViewById(R.id.contactlist_name);
call_contact = (Button) itemView.findViewById(R.id.contactlist_call);
}
public void setData(int position) {
this.position = position;
//String displayContacts=((DisplayContacts) context).selectedContactName.get(position);
String displayContacts=Common.selectedContactName.get(position);
Toast.makeText(context,"name to display"+ displayContacts,Toast.LENGTH_SHORT).show();
//name_contactList.setText(((DisplayContacts) context).selectedContactName.get(position));
//name_contactList.setText(displayContacts);
name_contactList.setText("dummy text");
}
#Override
public void onClick(View v) {
//sendPushNotification();
startAudioCall();
}
public void setListeners() {
call_contact.setOnClickListener(displayViewHolder.this);
}
}
public void startAudioCall() {
Intent i = new Intent(context, AudioCallActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
#Override
public int getItemCount() {
return ((DisplayContacts) context).selectedContactName.size();
}
}
can be one of two things:
1.you are not attaching the adapter with data,hence empty
2.or you are updating your data but not calling notifyDataSetChanged()
try to pass the list data in your Adapter class while you are creating it,then attach it to the recyelerview.
//to give a vary basic example
List dataList;
RvAdapter(Context c,List data){
this.dataList=data;
}
onBidViewHolder(Viewholder holder,int position){
holder.tvName.setText(dataList.get(position).getName());
.......
}
//in your activity/fragment
RvAdapter adapter=new RavAdapter(context,dataList);
recylerview.setAdapter(adapter);
//if you change your data
adapter.notifyDataSetChanged()
I've been working on adapter and tried to update it with notifydatasetchanged. But the problem I face is that after i successfully update the adapter where I can see the changes have been made in the listview, it will then change back to previous data after I return from other fragment. I've heard that adapter will reuse the convert view with same data which cause the problem, but I don't know how to fix this. I've searched for the answer but couldn't find anything similar as most of the answers were all about declaring a new adapter.
Below is part of my code:
1.refresh method in fragment
public void toggleRefreshInBackground(ArrayList<HashMap<String, Object>> list) {
dialog_list.clear();
dialog_list.addAll(list);
adapter.update(list);
}
2.getView() of my adapter
public class DialogListAdapter extends BaseAdapter {
Context context;
private ImageLoader imageLoader;
private static LayoutInflater inflater;
private ArrayList<HashMap<String, Object>> member_list;
private ArrayList<HashMap<String, Object>> member_list2;
private SparseBooleanArray mSelectedItemsIds;
private ArrayList<Integer> selectedItemPosition;
//private static final int droidGreen = Color.parseColor("#A4C639");
//private BadgeView badge;
Resources res;
String sorting;
public DialogListAdapter(Context c,
ArrayList<HashMap<String, Object>>content, String temp_sorting) {
inflater=(LayoutInflater)c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.context=c;
this.member_list = content;
this.member_list2 = new ArrayList<>();
this.member_list2.addAll(this.member_list);
res=c.getResources();
this.sorting = temp_sorting;
mSelectedItemsIds = new SparseBooleanArray();
selectedItemPosition = new ArrayList<>();
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return member_list.size();
}
#Override
public HashMap<String, Object> getItem(int position) {
// TODO Auto-generated method stub
return member_list.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public void update(ArrayList<HashMap<String,Object>> obj) {
member_list2.clear();
member_list2.addAll(obj);
notifyDataSetChanged();
}
public final class DialogListItem{ // view holder
public TextView read_count;
public TextView nameView;
public TextView numberView;
public TextView statusView;
public ImageView thumb_image;
public TextView timeView;
public TextView senderView;
public ImageView tick;
//public BadgeView badge;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
int index;
if(sorting.equals("D")){
index = member_list.size()-position-1;
}else{
index = position;
}
View row = convertView;
DialogListItem dialogItem=null;
String textbuff_time = null;
String textbuff_mess = null;
String textbuff_sender = null;
if (convertView==null){
row=inflater.inflate(R.layout.dialog_list_single, null);
dialogItem=new DialogListItem();
dialogItem.read_count=(TextView)row.findViewById(R.id.readcount);
dialogItem.nameView=(TextView)row.findViewById(R.id.member_name);
dialogItem.numberView=(TextView)row.findViewById(R.id.tab2number);
dialogItem.statusView=(TextView)row.findViewById(R.id.tab2status);
dialogItem.thumb_image=(ImageView)row.findViewById(R.id.tab2image);
dialogItem.timeView=(TextView) row.findViewById(R.id.tab2date);
dialogItem.senderView=(TextView) row.findViewById(R.id.tab2sender);
dialogItem.tick = (ImageView) row.findViewById(R.id.tick);
row.setTag(dialogItem);
}
else{
dialogItem=(DialogListItem) row.getTag();
}
if (mSelectedItemsIds.get(position)) {
row.setBackgroundColor(context.getResources().getColor(R.color.item_selected));
} else {
row.setBackgroundColor(context.getResources().getColor(R.color.item_unselected));
}
HashMap<String,Object>items;
items=member_list.get(index);
dialogItem.nameView.setText((String)items.get(DBhelper.MEMBER_NAME));
dialogItem.nameView.setTypeface(null,Typeface.BOLD);
dialogItem.nameView.setSingleLine(true);
dialogItem.nameView.setMaxLines(1);
dialogItem.nameView.setEms(13);
dialogItem.nameView.setEllipsize(TruncateAt.END);
dialogItem.numberView.setText((String)items.get(DBhelper.MEMBER_NUMBER));
String textbuff=(String)items.get(DBhelper.MEMBER_LMESSAGE);
if (!TextUtils.isEmpty(textbuff)){
textbuff_time=textbuff.substring(0, 19);
textbuff_mess=textbuff.substring(20);
int bound=textbuff_mess.indexOf("½");
if(bound!=-1){
textbuff_sender=textbuff_mess.substring(0,bound);
textbuff_mess=textbuff_mess.substring(bound+2);
}
else
textbuff_sender="";
dialogItem.statusView.setText(textbuff_mess);
if (textbuff_sender.equals(context.getResources().getString(R.string.myself))) {
dialogItem.senderView.setVisibility(View.GONE);
dialogItem.tick.setVisibility(View.VISIBLE);
} else {
textbuff_sender = textbuff_sender + ": ";
dialogItem.senderView.setVisibility(View.VISIBLE);
dialogItem.senderView.setText(textbuff_sender);
dialogItem.tick.setVisibility(View.GONE);
}
try {
dialogItem.timeView.setText(Utility.relativeTime(row.getContext(), textbuff_time));
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else{
dialogItem.statusView.setText("");
dialogItem.senderView.setText("");
dialogItem.timeView.setText("---");
}
dialogItem.statusView.setTextColor(Color.GRAY);
dialogItem.statusView.setTypeface(null,Typeface.NORMAL);
dialogItem.timeView.setTextColor(Color.GRAY);
dialogItem.timeView.setTypeface(null,Typeface.NORMAL);
dialogItem.senderView.setTextColor(Color.GRAY);
dialogItem.senderView.setTypeface(null,Typeface.NORMAL);
dialogItem.senderView.getPaint().setTextSkewX(-0.25f);
String sformat=" "+String.valueOf(items.get(DBhelper.MEMBER_SIZE))+" ";
dialogItem.read_count.setText(sformat);
int badge_number=(Integer)items.get(DBhelper.MEMBER_SIZE);
if(badge_number>0){
dialogItem.read_count.setVisibility(View.VISIBLE);
dialogItem.statusView.setTextColor(Color.BLACK);
dialogItem.statusView.setTypeface(null,Typeface.BOLD);
dialogItem.timeView.setTextColor(Color.BLACK);
dialogItem.timeView.setTypeface(null,Typeface.BOLD);
dialogItem.senderView.setTextColor(Color.BLACK);
dialogItem.senderView.setTypeface(null,Typeface.BOLD);
dialogItem.senderView.getPaint().setTextSkewX(-0.25f);
}
else{
dialogItem.read_count.setVisibility(View.GONE);
}
StringBuffer link=new StringBuffer(Register.get_current_server_address());
if(items.get(DBhelper.MEMBER_TYPE).equals(res.getString(R.string.broadcast_chat))){
dialogItem.nameView.setTextColor(row.getResources().getColor(R.color.tab4_title));
link.append("uniappSystemFile.asp");
link.append("?file=").append("broadcast.png");
//imageLoader.DisplayImage(link.toString(), dialogItem.thumb_image);
Picasso.with(context).load(link.toString()).transform(new CircleTransform()).resize(200,200).into(dialogItem.thumb_image);
dialogItem.read_count.setVisibility(View.GONE); // disable broadcast badge
}
Picasso.with(context).load(R.drawable.ic_contact).resize(200,200).into(dialogItem.thumb_image);
Picasso.with(context).load(R.drawable.ic_notif).resize(200, 200).into(dialogItem.thumb_image);
}else{
link2 = new IMService(context.getApplicationContext()).group_image_thumb_get(tab2.myphone, (String) items.get(DBhelper.MEMBER_NUMBER));
dialogItem.nameView.setTextColor(row.getResources().getColor(R.color.tab3_title));
//imageLoader.DisplayImage(link2, dialogItem.thumb_image);
Picasso.with(context).load(link2).transform(new CircleTransform()).resize(200, 200).placeholder(R.drawable.ic_group_circle_black_48dp).error(R.drawable.ic_group_circle_black_48dp).into(dialogItem.thumb_image);
}
}
public void setSearchPattern(String pattern) {
filterListByPattern(pattern.trim());
this.notifyDataSetChanged();
}
private void filterListByPattern(String searchPattern) {
member_list.clear();
for (HashMap<String,Object> info : member_list2) {
boolean add = true;
do {
if (searchPattern == null || searchPattern.equals("")) {
break;
}
if (info.get(DBhelper.MEMBER_NAME).toString().toLowerCase().contains(searchPattern)) {
break;
}
add = false;
} while (false);
if (add) {
member_list.add(info);
}
}
}
public void resetList() {
this.member_list2 = new ArrayList<HashMap<String,Object>>();
this.member_list2.addAll(this.member_list);
this.notifyDataSetChanged();
}
public void remove(Object object) {
member_list.remove(object);
notifyDataSetChanged();
}
public void toggleSelection(int position) {
selectView(position, !mSelectedItemsIds.get(position));
}
public void removeSelection() {
mSelectedItemsIds = new SparseBooleanArray();
selectedItemPosition = new ArrayList<>();
notifyDataSetChanged();
}
public void selectView(int position, boolean value) {
if (value) {
mSelectedItemsIds.put(position, value);
selectedItemPosition.add(position);
} else {
mSelectedItemsIds.delete(position);
selectedItemPosition.remove(selectedItemPosition.indexOf(position));
}
notifyDataSetChanged();
}
public int getSelectedCount() {
return mSelectedItemsIds.size();
}
public SparseBooleanArray getSelectedIds() {
return mSelectedItemsIds;
}
public ArrayList<Integer> getItemPosition() {
return selectedItemPosition;
}
}
So, my question is why would my adapter and listview show the old data after I return from other fragment to this fragment, and how to fix this?
P.S. please don't tell me to declare a new adapter like this
adapter = new MyAdapter(list);
adapter.notifyDataSetChanged();
I know it works, but it's not a good and appropriate approach since it's a heavy operation and you don't even need to use notifyDataSetChanged after declaring a new adapter.
Many thanks
Try putting setRetainInstance(true);
inside your fragment.
If above does not work then try with onSaveInstanceState() as below -
Declare at top, Parcelable state;
Save listview state, state = listview.onSaveInstanceState(); inside onpause() of fragment or manually while changing fragment.
Then inside onCreateView check state is null or not. If null then set adapter / get data, if not then set
listview.onRestoreInstanceState(state);
On the other hand, Each time you load fragment, ArrayList will start off empty. So you need to be careful to save data.
I've got problem with my ListView. I'm creating new object and add it to the database by clicking button in the first fragment. In the second fragment I've got listview with objects from my database. Everything works fine but listView in the second fragment doesn't refresh - I see new objects only after restarting app. All solutions like : notifyDataSetChanged don't work :/
Here's my adapter from first fragment:
public class ConcertAdapter extendsRecyclerView.Adapter<ConcertAdapter.MyViewHolder> {
private static final String FRAGMENT_TAG = "fragmentTag";
private static final String TAG = ConcertAdapter.class.getSimpleName() ;
private LayoutInflater inflater;
private Context context;
private List<Concert> concertList = new ArrayList<>();
private DatabaseHelper mDatabaseHelper = null;
private int selectedRecordPosition = -1;
private MainActivity mActivity;
public ConcertAdapter(Context context, List<Concert> concerts, MainActivity mainActivity) {
this.inflater = LayoutInflater.from(context);
this.concertList = concerts;
this.context = context;
this.mActivity = mainActivity;
}
public void setListConcert(ArrayList<Concert> concertList) {
this.concertList = concertList;
notifyItemRangeChanged(0, concertList.size());
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.from(parent.getContext()).inflate(R.layout.concert_item, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
final float screenWidthPx = holder.itemView.getResources().getDisplayMetrics().widthPixels;
Concert current = concertList.get(position);
Log.d("mLog", current.getUrl());
holder.mImage.setImageUrl(current.getUrl(), MySingleton.getInstance().getImageLoader());
holder.mImage.getLayoutParams().height = (int) (screenWidthPx * 0.50);
holder.mFav_btn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked) {
final Concert favConcert = new Concert();
favConcert.setTitle(concertList.get(position).getTitle());
favConcert.setContent(concertList.get(position).getContent());
favConcert.setDate(concertList.get(position).getDate());
favConcert.setUrl(concertList.get(position).getUrl());
try {
final Dao<Concert, Integer> concertDao = getHelper().getConcertDao();
concertDao.create(favConcert);
}catch (SQLException e) {
e.printStackTrace();
}
}
}
});
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date concertDate = new Date();
try {
concertDate = format.parse(current.getDate());
} catch (ParseException e) {
e.printStackTrace();
}
DateTime dt = new DateTime();
DateTime currentDate = dt.withZone(DateTimeZone.forID("Europe/Warsaw"));
int days = Days.daysBetween(new DateTime(currentDate), new DateTime(concertDate)).getDays();
String s = String.valueOf(days);
holder.mDate_btn.setText(s + " dni");
if (s.equals("0")) {
holder.mDate_btn.setText("dziś :)");
}
}
#Override
public int getItemCount() {
return concertList.size();
}
public void setConcerts(List<Concert> concerts) {
concertList = new ArrayList<>(concerts);
}
public void showDisplay(int position) {
Bundle bundle = new Bundle();
bundle.putInt("position", position);
bundle.putString("content", concertList.get(position).getContent());
bundle.putString("date", concertList.get(position).getDate());
bundle.putString("url", concertList.get(position).getUrl());
bundle.putString("title", concertList.get(position).getTitle());
Fragment fragment = new DisplayConcertFragment();
fragment.setArguments(bundle);
mActivity.replaceFragment(fragment);
}
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public NetworkImageView mImage;
public Button mDate_btn;
public TextView mBubble;
public ToggleButton mFav_btn;
public ImageView mBubbleImage;
private ConcertFragment mConcertFragment;
public MyViewHolder(View itemView) {
super(itemView);
mImage = (NetworkImageView) itemView.findViewById(R.id.concerts_niv);
mDate_btn = (Button) itemView.findViewById(R.id.date_btn);
mImage.setOnClickListener(this);
mFav_btn = (ToggleButton) itemView.findViewById(R.id.fav_btn);
}
#Override
public void onClick(View v) {
showDisplay(getAdapterPosition());
//ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);
Toast.makeText(context, "TEST", Toast.LENGTH_LONG).show();
}
public Concert removeItem(int position) {
final Concert concert = concertList.remove(position);
notifyItemRemoved(position);
return concert;
}
}
private DatabaseHelper getHelper() {
if (mDatabaseHelper == null) {
mDatabaseHelper = OpenHelperManager.getHelper(context,DatabaseHelper.class);
}
return mDatabaseHelper;
}
Here's my second adapter:
public class FavAdapter extends ArrayAdapter {
private LayoutInflater mInflater;
private List mRecords;
private Dao<Concert, Integer> concertDao;
private Button mDateButton;
private NetworkImageView mImage;
public FavAdapter(Context context, int resource, List objects, Dao<Concert, Integer> concertDao) {
super(context, resource, objects);
this.mRecords = objects;
this.concertDao = concertDao;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null)
convertView = mInflater.inflate(R.layout.concert_item, parent, false);
if(mRecords.get(position).getClass().isInstance(new Concert())){
final Concert concert = (Concert) mRecords.get(position);
mImage =((NetworkImageView)convertView.findViewById(R.id.concerts_niv));
mImage.setImageUrl(concert.getUrl(), MySingleton.getInstance().getImageLoader());
final float screenWidthPx = mImage.getResources().getDisplayMetrics().widthPixels;
mImage.getLayoutParams().height = (int) (screenWidthPx * 0.50);
mDateButton = (Button) convertView.findViewById(R.id.date_btn);
Date concertDate = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
concertDate = format.parse(concert.getDate());
} catch (ParseException e) {
e.printStackTrace();
}
DateTime dt = new DateTime();
DateTime currentDate = dt.withZone(DateTimeZone.forID("Europe/Warsaw"));
int days = Days.daysBetween(new DateTime(currentDate), new DateTime(concertDate)).getDays();
String s = String.valueOf(days);
mDateButton.setText(s + " dni");
if (s.equals("0")) {
mDateButton.setText("dziś :)");
}
// ((TextView)convertView.findViewById(R.id.teacher_tv)).setText(studentDetails.teacher.teacherName);
}
return convertView;
}
}
And here's my second fragment with ListView:
public class FavFragment extends Fragment {
private static final String TAG = FavFragment.class.getSimpleName() ;
private DatabaseHelper mDatabaseHelper = null;
private ListView mListView;
private int selectedRecordPosition = -1;
private Dao<Concert, Integer> concertDao;
private List<Concert> concertList;
private MainActivity mActivity;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_fav_layout, container, false);
mListView = (ListView)v.findViewById(R.id.concerts_lv);
mActivity = (MainActivity) getContext();
try {
concertDao = getHelper().getConcertDao();
concertList = concertDao.queryForAll();
FavAdapter adapter = new FavAdapter(getContext(), R.layout.concert_item, concertList, concertDao);
mListView.setAdapter(adapter);
adapter.notifyDataSetChanged();
mListView.invalidateViews();
mListView.refreshDrawableState();
} catch (SQLException e) {
e.printStackTrace();
}
Log.e(TAG, "onCreateView notify");
return v;
}
private DatabaseHelper getHelper() {
if (mDatabaseHelper == null) {
mDatabaseHelper = OpenHelperManager.getHelper(getContext(), DatabaseHelper.class);
}
return mDatabaseHelper;
}
#Override
public void onDestroy() {
super.onDestroy();
if (mDatabaseHelper != null) {
OpenHelperManager.releaseHelper();
mDatabaseHelper = null;
}
}
}
Here's my first fragment
public class ConcertFragment extends Fragment implements MyBackPressed {
private static final String FRAGMENT_TAG = "fragmentTag";
private static final String TAG = ConcertFragment.class.getSimpleName() ;
public ProgressBar progress;
private ConcertLoader concertLoader;
private RecyclerView recyclerView;
private Context mContext;
private android.support.v4.app.FragmentManager mFragmentManager;
private MainActivity mActivity;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
JodaTimeAndroid.init(getContext());
View v = inflater.inflate(R.layout.fragment_concert_layout, container, false);
progress = (ProgressBar) v.findViewById(R.id.progressBar);
recyclerView = (RecyclerView) v.findViewById(R.id.concerts_rv);
concertLoader = new ConcertLoader(ConcertFragment.this);
mActivity = (MainActivity) getContext();
futureConcerts();
return v;
}
public void futureConcerts() {
concertLoader.execute();
getActivity().getWindow().getDecorView().getRootView().setClickable(false);
}
public void notifyAboutListCreation(List<Concert> res) {
ConcertAdapter adapter = new ConcertAdapter(getActivity().getApplicationContext(), res, mActivity);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity().getApplicationContext()));
progress.setVisibility(View.GONE);
adapter.notifyDataSetChanged();
}
#Override
public void onBackPressed() {
getActivity().finish();
}
}
I had similar problems a while ago. Are you triggering any UI updates from non-UI threads? Maybe from within listeners? Try using the following code where the UI updates are triggered.
runOnUiThread(new Runnable(){
#Override
public void run(){
...
adapter.notifyDataSetChanged();
mListView.invalidateViews();
mListView.refreshDrawableState();
...
}
});
Personally, I now have started to wrap any problematic code blocks in a generic try-catch block that catches Exception and see if there are any exceptions I migh thave overseen (using logcat on terminal with tag filter).
(Cannot comment yet, so answering in this way)
I can show images in gridview normally. However, I want to use pulltorefresh functionality and I found a library to get the functionality. I am confused how to integrate my images.
Now, the gridview just shows imagelinks in the array. How can I use imageAdapter instead of arrayAdapter to show the Images?
Thanks a lot.
This is the activity class:
public final class PullToRefreshGridActivity extends Activity {
static final int MENU_SET_MODE = 0;
private LinkedList<String> mListItems;
private PullToRefreshGridView mPullRefreshGridView;
private GridView mGridView;
private ArrayAdapter<String> mAdapter;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ptr_grid);
mPullRefreshGridView = (PullToRefreshGridView) findViewById(R.id.pull_refresh_grid);
mGridView = mPullRefreshGridView.getRefreshableView();
// Set a listener to be invoked when the list should be refreshed.
mPullRefreshGridView.setOnRefreshListener(new OnRefreshListener2<GridView>() {
#Override
public void onPullDownToRefresh(PullToRefreshBase<GridView> refreshView) {
Toast.makeText(PullToRefreshGridActivity.this, "Pull Down!", Toast.LENGTH_SHORT).show();
new GetDataTask().execute();
}
#Override
public void onPullUpToRefresh(PullToRefreshBase<GridView> refreshView) {
Toast.makeText(PullToRefreshGridActivity.this, "Pull Up!", Toast.LENGTH_SHORT).show();
new GetDataTask().execute();
}
});
mListItems = new LinkedList<String>();
TextView tv = new TextView(this);
tv.setGravity(Gravity.CENTER);
tv.setText("Empty View, Pull Down/Up to Add Items");
mPullRefreshGridView.setEmptyView(tv);
mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mListItems);
mGridView.setAdapter(mAdapter);
}
private class GetDataTask extends AsyncTask<Void, Void, String[]> {
#Override
protected String[] doInBackground(Void... params) {
// Simulates a background job.
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
return mStrings;
}
#Override
protected void onPostExecute(String[] result) {
mListItems.addFirst("Added after refresh...");
mListItems.addAll(Arrays.asList(result));
mAdapter.notifyDataSetChanged();
// Call onRefreshComplete when the list has been refreshed.
mPullRefreshGridView.onRefreshComplete();
super.onPostExecute(result);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, MENU_SET_MODE, 0,
mPullRefreshGridView.getMode() == Mode.BOTH ? "Change to MODE_PULL_DOWN"
: "Change to MODE_PULL_BOTH");
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem setModeItem = menu.findItem(MENU_SET_MODE);
setModeItem.setTitle(mPullRefreshGridView.getMode() == Mode.BOTH ? "Change to MODE_PULL_FROM_START"
: "Change to MODE_PULL_BOTH");
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_SET_MODE:
mPullRefreshGridView
.setMode(mPullRefreshGridView.getMode() == Mode.BOTH ? Mode.PULL_FROM_START
: Mode.BOTH);
break;
}
return super.onOptionsItemSelected(item);
}
private String[] mStrings = {"https://lh6.googleusercontent.com/-55osAWw3x0Q/URquUtcFr5I/AAAAAAAAAbs/rWlj1RUKrYI/s1024/A%252520Photographer.jpg",
"https://lh4.googleusercontent.com/--dq8niRp7W4/URquVgmXvgI/AAAAAAAAAbs/-gnuLQfNnBA/s1024/A%252520Song%252520of%252520Ice%252520and%252520Fire.jpg",
"https://lh5.googleusercontent.com/-7qZeDtRKFKc/URquWZT1gOI/AAAAAAAAAbs/hqWgteyNXsg/s1024/Another%252520Rockaway%252520Sunset.jpg",
"https://lh3.googleusercontent.com/--L0Km39l5J8/URquXHGcdNI/AAAAAAAAAbs/3ZrSJNrSomQ/s1024/Antelope%252520Butte.jpg",
"https://lh6.googleusercontent.com/-8HO-4vIFnlw/URquZnsFgtI/AAAAAAAAAbs/WT8jViTF7vw/s1024/Antelope%252520Hallway.jpg",
"https://lh4.googleusercontent.com/-WIuWgVcU3Qw/URqubRVcj4I/AAAAAAAAAbs/YvbwgGjwdIQ/s1024/Antelope%252520Walls.jpg",
"https://lh6.googleusercontent.com/-UBmLbPELvoQ/URqucCdv0kI/AAAAAAAAAbs/IdNhr2VQoQs/s1024/Apre%2525CC%252580s%252520la%252520Pluie.jpg",
"https://lh3.googleusercontent.com/-s-AFpvgSeew/URquc6dF-JI/AAAAAAAAAbs/Mt3xNGRUd68/s1024/Backlit%252520Cloud.jpg",
"https://lh5.googleusercontent.com/-bvmif9a9YOQ/URquea3heHI/AAAAAAAAAbs/rcr6wyeQtAo/s1024/Bee%252520and%252520Flower.jpg",
"https://lh5.googleusercontent.com/-n7mdm7I7FGs/URqueT_BT-I/AAAAAAAAAbs/9MYmXlmpSAo/s1024/Bonzai%252520Rock%252520Sunset.jpg",
"https://lh6.googleusercontent.com/-4CN4X4t0M1k/URqufPozWzI/AAAAAAAAAbs/8wK41lg1KPs/s1024/Caterpillar.jpg",
"https://lh3.googleusercontent.com/-rrFnVC8xQEg/URqufdrLBaI/AAAAAAAAAbs/s69WYy_fl1E/s1024/Chess.jpg",
"https://lh5.googleusercontent.com/-WVpRptWH8Yw/URqugh-QmDI/AAAAAAAAAbs/E-MgBgtlUWU/s1024/Chihuly.jpg",};
}
Create a custom Adapter, where you refresh each cell. Create an object which contains a String and Image property, in GetDataTask create an ArrayList of all those new objects and refresh your adapter.
Heres a simple example of the adapter and object
public class CustomStepsAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<CustomObject> details;
private LayoutInflater mInflater;
public CustomStepsAdapter(Context aContext, ArrayList<CustomObject> data) {
this.details = data;
this.mContext = aContext;
mInflater = LayoutInflater.from(aContext);
}
public int getCount() {
return details.size();
}
public CustomObject getItem(int position) {
return details.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView() {
return mInflater.inflate(R.layout.custom_step_options_cell, null);
}
public View getView(int position, View convertView, ViewGroup parent) {
final CustomObject item = getItem(position);
CustomStepCell cell = null;
if (convertView == null) {
convertView = getView();
cell = new CustomStepCell();
cell.itemName = (TextView) convertView.findViewById(R.id.option_name);
cell.image = (ImageView) convertView.findViewById(R.id.green_checkmark);
convertView.setTag(cell);
}
else
{
cell = (CustomStepCell) convertView.getTag();
}
cell.itemName.setText(item.getItemName());
cell.image = item.getImage();
return convertView;
}
public boolean isShowPrices() {
return showPrices;
}
public void setShowPrices(boolean showPrices) {
this.showPrices = showPrices;
}
public static class CustomStepCell
{
public TextView itemName;
public ImageView image;
}
}
public class CustomObject
{
private String itemName;
private ImageView image;
public CustomObject()
{
this.itemName = "";
}
public void setImage(ImageView anImage)
{
this.image = anImage;
}
public void setItemName(String anItemName)
{
this.itemName = anItemName;
}
public ImageView getImage()
{
return this.image;
}
public String getItemName()
{
return this.itemName;
}
}