Android viewholder class wide scope - java

I have a list adapter using a viewholder pattern, my problem is I need to update a TextView from the viewholder in onpostexecute() of an AsyncTask contained within the same class, but this always returns a nullpointer on the TextView, how can give my textviews from the viewholder enough scope that I can change them in teh AsyncTask? I will include a code example below, thanks in adcvance
public class ListAdapter extends BaseAdapter {
TextView tvA1, tvA2;
Integer submitId;
String submitQuestion;
public ListAdapter() {
....
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
friendsViewHolder holder = null;
if (convertView == null) {
holder = new friendsViewHolder();
convertView = inflater.inflate(R.layout.list_item_status, null);
holder.tvA1 = (TextView) convertView
.findViewById(R.id.tvA1);
holder.tvA2 = (TextView) convertView
.findViewById(R.id.tvA2);
holder.btQ1 = (LinearLayout) convertView
.findViewById(R.id.btConfirm);
holder.btQ2 = (LinearLayout) convertView
.findViewById(R.id.btDeny);
convertView.setTag(holder);
} else {
holder = (friendsViewHolder) convertView.getTag();
}
tvA1 = holder.tvA1;
tvA2 = holder.tvA2;
holder.btQ1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
submitId = id;
submitQuestion = q1;
new UpdateAnswer().execute();
}
});
holder.btQ2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
submitId = id;
submitQuestion = q2;
new UpdateAnswer().execute();
}
});
return convertView;
}
static class friendsViewHolder {
TextView tvA1, tvA2;
LinearLayout btQ1, btQ2;
}
private class UpdateAnswer extends AsyncTask<Void, Void, ArrayList<Object>> {
#Override
protected ArrayList<Object> doInBackground(Void... params) {
return apiHelper.submitAnswer(submitId, submitQuestion);
}
#Override
protected void onPostExecute(ArrayList<Object> answers) {
super.onPostExecute(answers);
if (answers != null) {
Integer a1 = (Integer) answers.get(1);
Integer a2 = (Integer) answers.get(2);
//Error here
tvA1.setText(a1);
tvA1.setVisibility(View.VISIBLE);
//error here
tvA2.setText(a2);
tvA2.setVisibility(View.VISIBLE);
}
}
}
}

Lets change few things here and there :)
Lets make friendsViewHolder public, also i need to add that in java it is somehow custom to name classes with names starting with cammel case simply put FirstLetterOfEeachWordIsBig :)
Lets add constructor to Update task :)
private class UpdateAnswer extends AsyncTask<Void, Void, ArrayList<Object>> {
int submitId;
String submitQuestion;
friendsViewHolder holder;
public UpdateAnswer (int submitId, String submitQuestion, friendsViewHolder holder) {
this.submitId = submitId;
this.submitQuestion = submitQuestion;
this.holder = holder;
}
On click lets change to
final frendsViewHolder finalHolder = holder;
holder.btQ1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new UpdateAnswer(id, q1, finalHolder).execute();
}
});
We are no longer in need of global TvA1, tvA2, submitId, submitQuestion;
And lastly we need to edit onPostExecute, hovewer i think that want be so hard since you have holder value forwarded :)
holder.tvA1.setText(a1);
holder.tvA1.setVisibility(View.VISIBLE);
holder.tvA2.setText(a2);
holder.tvA2.setVisibility(View.VISIBLE);
In java you can create constructor to allow passing additional data to object, we use this to set id, question and holder for our task, and for passing that information to other object we should'nt be using global values (they can be changed by every process), think about situation when your call "apiHelper.submitAnswer(submitId, submitQuestion)" would take long to proceed (half a second for example), then user click within half a second on answer in first and answer c on 3 question, by passing values globally you cant determine wich answer to accept :)
Cheers :)

Java is pass by value, but you can send reference of an Object in the value. I have used the above, and sent reference of holder to AsyncTask.
public class ListAdapter extends BaseAdapter {
TextView tvA1, tvA2;
Integer submitId;
String submitQuestion;
public ListAdapter() {
....
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
friendsViewHolder holder = null;
if (convertView == null) {
holder = new friendsViewHolder();
convertView = inflater.inflate(R.layout.list_item_status, null);
holder.tvA1 = (TextView) convertView
.findViewById(R.id.tvA1);
holder.tvA2 = (TextView) convertView
.findViewById(R.id.tvA2);
holder.btQ1 = (LinearLayout) convertView
.findViewById(R.id.btConfirm);
holder.btQ2 = (LinearLayout) convertView
.findViewById(R.id.btDeny);
convertView.setTag(holder);
} else {
holder = (friendsViewHolder) convertView.getTag();
}
holder.btQ1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
submitId = id;
submitQuestion = q1;
new UpdateAnswer(holder).execute();
}
});
holder.btQ2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
submitId = id;
submitQuestion = q2;
new UpdateAnswer().execute();
}
});
return convertView;
}
static class friendsViewHolder {
TextView tvA1, tvA2;
LinearLayout btQ1, btQ2;
}
private class UpdateAnswer extends AsyncTask<Void, Void, ArrayList<Object>> {
friendsViewHolder holder;
UpdateAnswer(friendsViewHolder holder)
{
this.holder = holder;
}
#Override
protected ArrayList<Object> doInBackground(Void... params) {
return apiHelper.submitAnswer(submitId, submitQuestion);
}
#Override
protected void onPostExecute(ArrayList<Object> answers) {
super.onPostExecute(answers);
if (answers != null) {
Integer a1 = (Integer) answers.get(1);
Integer a2 = (Integer) answers.get(2);
//Error here
holder.tva1.setText(a1);
holder.tva1.setVisibility(View.VISIBLE);
//error here
holder.tva2.setText(a2);
holder.tva2.setVisibility(View.VISIBLE);
}
}
}
}

Related

attempting to use incompatible return type

Can someone help me with this error that I keep getting? The program that I'm trying to implement admob banner ad between items in recyclerview. every thing is ok but still this one error that blocked me from go on.
public class RecipeAdapter extends RecyclerView.Adapter<RecipeAdapter.ViewHolder> {
public static final String TAG = RecipeAdapter.class.getSimpleName();
public static final HashMap<String, Integer> LABEL_COLORS = new HashMap<String, Integer>() {{
put("Low-Carb", R.color.colorLowCarb);
put("Low-Fat", R.color.colorLowFat);
put("Low-Sodium", R.color.colorLowSodium);
put("Medium-Carb", R.color.colorMediumCarb);
put("Vegetarian", R.color.colorVegetarian);
put("Balanced", R.color.colorBalanced);
}};
private Context mContext;
private LayoutInflater mInflater;
private ArrayList<Recipe> mDataSource;
private static final int DEFAULT_VIEW_TYPE = 1;
private static final int NATIVE_AD_VIEW_TYPE = 2;
public RecipeAdapter(Context context, ArrayList<Recipe> items) {
mContext = context;
mDataSource = items;
mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); }
#Override public int getItemViewType(int position) {
// Change the position of the ad displayed here. Current is after 5
if ((position + 1) % 6 == 0) {
return NATIVE_AD_VIEW_TYPE;
}
return DEFAULT_VIEW_TYPE; }
#NonNull
#Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
LayoutInflater layoutInflater = LayoutInflater.from(mContext);
switch (viewType) {
default:
view = layoutInflater
.inflate(R.layout.list_item_native_ad, parent, false);
return new ViewHolder(view);
case NATIVE_AD_VIEW_TYPE:
view = layoutInflater.inflate(R.layout.list_item_native_ad, parent, false);
return new ViewHolderAdMob(view);
}
}
#Override public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
// Get relevant subviews of row view
TextView titleTextView = holder.titleTextView;
TextView subtitleTextView = holder.subtitleTextView;
TextView detailTextView = holder.detailTextView;
ImageView thumbnailImageView = holder.thumbnailImageView;
//Get corresponding recipe for row final Recipe recipe = (Recipe) getItem(position);
// Update row view's textviews to display recipe information
titleTextView.setText(recipe.title);
subtitleTextView.setText(recipe.description);
detailTextView.setText(recipe.label);
// Use Picasso to load the image. Temporarily have a placeholder in case it's slow to load
Picasso.with(mContext).load(recipe.imageUrl).placeholder(R.mipmap
.ic_launcher).into(thumbnailImageView);
holder.parentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent detailIntent = new Intent(mContext, RecipeDetailActivity.class);
detailIntent.putExtra("title", recipe.title);
detailIntent.putExtra("url", recipe.instructionUrl);
mContext.startActivity(detailIntent);
}
});
// Style text views
Typeface titleTypeFace = Typeface.createFromAsset(mContext.getAssets(),
"fonts/JosefinSans-Bold.ttf");
titleTextView.setTypeface(titleTypeFace);
Typeface subtitleTypeFace = Typeface.createFromAsset(mContext.getAssets(),
"fonts/JosefinSans-SemiBoldItalic.ttf");
subtitleTextView.setTypeface(subtitleTypeFace);
Typeface detailTypeFace = Typeface.createFromAsset(mContext.getAssets(),
"fonts/Quicksand-Bold.otf");
detailTextView.setTypeface(detailTypeFace);
detailTextView.setTextColor(android.support.v4.content.ContextCompat.getColor(mContext, LABEL_COLORS
.get(recipe.label)));
}
#Override public int getItemCount() {
return mDataSource.size(); }
#Override public long getItemId(int position) {
return position; }
public Object getItem(int position) {
return mDataSource.get(position); }
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView titleTextView;
private TextView subtitleTextView;
private TextView detailTextView;
private ImageView thumbnailImageView; private View parentView;
public ViewHolder(#NonNull View view){
super(view);
// create a new "Holder" with subviews
this.parentView = view;
this.thumbnailImageView = (ImageView) view.findViewById(R.id.recipe_list_thumbnail);
this.titleTextView = (TextView) view.findViewById(R.id.recipe_list_title);
this.subtitleTextView = (TextView) view.findViewById(R.id.recipe_list_subtitle);
this.detailTextView = (TextView) view.findViewById(R.id.recipe_list_detail);
// hang onto this holder for future recyclage
view.setTag(this);
}
}
public class ViewHolderAdMob extends RecyclerView.ViewHolder {
private final AdView mNativeAd;
public ViewHolderAdMob(View itemView) {
super(itemView);
mNativeAd = itemView.findViewById(R.id.nativeAd);
mNativeAd.setAdListener(new AdListener() {
#Override
public void onAdLoaded() {
super.onAdLoaded();
// if (mItemClickListener != null) {
Log.i("AndroidBash", "onAdLoaded");
// }
}
#Override
public void onAdClosed() {
super.onAdClosed();
// if (mItemClickListener != null) {
Log.i("AndroidBash", "onAdClosed");
// }
}
#Override
public void onAdFailedToLoad(int errorCode) {
super.onAdFailedToLoad(errorCode);
// if (mItemClickListener != null) {
Log.i("AndroidBash", "onAdFailedToLoad");
// }
}
#Override
public void onAdLeftApplication() {
super.onAdLeftApplication();
// if (mItemClickListener != null) {
Log.i("AndroidBash", "onAdLeftApplication");
// }
}
#Override
public void onAdOpened() {
super.onAdOpened();
// if (mItemClickListener != null) {
Log.i("AndroidBash", "onAdOpened");
// }
}
});
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice("") // Remove this before publishing app
.build();
mNativeAd.loadAd(adRequest);
}
}
}
The return type needs to be whatever ViewHolder type you declared for your adapter class.
For example, from the Android RecyclerView example page:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
// ^^^^^^^^^^^^^^^^^^^^^^
// It should return this type ^
public static class MyViewHolder extends RecyclerView.ViewHolder {
// your adapter
}
#Override
public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
// Note: returns MyAdapter.MyViewHolder, not RecyclerView.ViewHolder
}
}
In your case, you have
public class RecipeAdapter extends RecyclerView.Adapter<RecipeAdapter.ViewHolder>
which means your onCreateViewHolder has to return RecipeAdapter.ViewHolder not RecyclerView.ViewHolder.
There is a separate issue too, which is that you have two ViewHolder types in the same adapter. To do this, you would need to change the ViewHolder type that your RecyclerView is based on to the generic type (RecyclerView.ViewHolder).
Please review this question, it has good answers for how to do this.

Pass data in other activity

I have to pass my value from one activity to other one.
I download data from database with Json and it works propelly.
My First Activity:
public class ListAdapter extends BaseAdapter
{
Context context;
List<cources> valueList;
HashMap<String, String> resultp = new HashMap<String, String>();
public ListAdapter(List<cources> listValue, Context context)
{
this.context = context;
this.valueList = listValue;
}
#Override
public int getCount()
{
return this.valueList.size();
}
#Override
public Object getItem(int position)
{
return this.valueList.get(position);
}
#Override
public long getItemId(int position)
{
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewItem viewItem = null;
if(convertView == null)
{
viewItem = new ViewItem();
LayoutInflater layoutInfiater = (LayoutInflater)this.context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
//LayoutInflater layoutInfiater = LayoutInflater.from(context);
convertView = layoutInfiater.inflate(R.layout.list_adapter_view_test, null);
viewItem.txtTitle = (TextView)convertView.findViewById(R.id.nome_prodotto);
viewItem.txtDescription = (TextView)convertView.findViewById(R.id.descrizione_prodotto);
viewItem.txtPrice = (TextView)convertView.findViewById(R.id.prezzo);
convertView.setTag(viewItem);
}
else
{
viewItem = (ViewItem) convertView.getTag();
}
viewItem.txtPrice.setText(valueList.get(position).prezzo_prodotto);
viewItem.txtTitle.setText(valueList.get(position).nome_prodotto);
viewItem.txtDescription.setText(valueList.get(position).descrizione_prodotto);
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// Get the position
Intent intent = new Intent(context, Dettaglio_Prodotto.class);
// Pass all data country
intent.putExtra("nome_prodotto", "test");
// Start SingleItemView Class
context.startActivity(intent);
}
});
return convertView;
}
}
class ViewItem
{
TextView txtTitle;
TextView txtDescription;
TextView txtPrice;
}
I have to pass the value of:
viewItem.txtPrice.setText(valueList.get(position).prezzo_prodotto);
My Second Activity i have the code:
Intent i = getIntent();
nome_prodotto = i.getStringExtra("nome_prodotto");
How i can do it?
if i put:
intent.putExtra("nome_prodotto",viewItem.txtTitle.setText(valueList.get(position).nome_prodo‌​tto));
i have the error:
Variable is accessed within inner class. Needs to be declared final
Suggestion: Use an ArrayAdapter rather than BaseAdapter if you are using List data anyway.
As the IDE indicates, make a final variable.
...
else
{
viewItem = (ViewItem) convertView.getTag();
}
// This is the item in the current position
final cources item = (cources) getItem(position);
Then, you can use that instead of repeatedly calling valueList.get(position)
viewItem.txtPrice.setText(item.prezzo_prodotto);
viewItem.txtTitle.setText(item.nome_prodotto);
viewItem.txtDescription.setText(item.descrizione_prodotto);
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// Get the position
Intent intent = new Intent(context, Dettaglio_Prodotto.class);
// Pass all data country
intent.putExtra("nome_prodo‌​tto", item.nome_prodo‌​tto);
// Start SingleItemView Class
context.startActivity(intent);
}
});
When you use valueList in a method that creates a new onTouchListener for an instance, that is an inner class.
Any variables accessed by that class has to be final or declared inside the class. Meanign if you create a new int inside the inner class, that doesn
t have to be final. But if the int is declared outside, it has to be final.
In your case, the variable position has to be marked as final
I guess you're trying to do something like this
intent.putExtra("nome_prodotto", valueList.get(position).prezzo_prodotto);
The method putExtra expects a key (String) and a value (in your case you're passing a string value).

Android RecyclerView:java.lang.NullPointerException: CartRecyclerAdapter$CustomViewHolder.getAdapterPosition()' on a null object reference

//This is my recycler view code and the error is Android RecyclerView:java.lang.NullPointerException: CartRecyclerAdapter$CustomViewHolder.getAdapterPosition()' on a null object reference
public class CartRecyclerAdapter extends RecyclerView.Adapter<CartRecyclerAdapter.CustomViewHolder> {
//this is declaration declaration of variables
private List<Cart> feedItemList;
private Context mContext;
private List<Cart> mDataset;
List<Cart> list = Collections.emptyList();
public CartRecyclerAdapter(Context context, List<Cart> feedItemList) {
this.feedItemList = feedItemList;
this.mContext = context;
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.cart_card, null);
CustomViewHolder viewHolder = new CustomViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(final CustomViewHolder customViewHolder, int i) {
final Cart feedItem = feedItemList.get(i);
if (customViewHolder.mealTitle!= null) {
customViewHolder.mealTitle.setText(feedItem.getMeal_title());
}
if (customViewHolder.mealPrice!= null) {
customViewHolder.mealPrice.setText(feedItem.getMeal_quanitity());
}
if (customViewHolder.mealQuantity!= null) {
customViewHolder.mealQuantity.setText(feedItem.getMeal_price());
}
//The error is coming from here
View.OnClickListener clickListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
CustomViewHolder holder = (CustomViewHolder) view.getTag();
int position = holder.getAdapterPosition();
//check here This is where the error os coming from
String numbers=feedItemList.get(position).toString();
feedItemList.remove(numbers);
}
};
customViewHolder.delete.setOnClickListener(clickListener);
customViewHolder.mealTitle.setTag(customViewHolder);
customViewHolder.mealPrice.setTag(customViewHolder);
customViewHolder.mealQuantity.setTag(customViewHolder);
setAnimation(customViewHolder, i);
}
//Method to remove but I don't know how to initialize.
public void removeAt(int position) {
mDataset.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position,mDataset.size());
}
#Override
public int getItemCount() {
return (null != feedItemList ? feedItemList.size() : 0);
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
protected CardView t;
protected ImageView thumbnail;
protected TextView mealTitle;
protected ImageView delete;
protected TextView mealPrice;
protected TextView mealQuantity;
public CustomViewHolder(View v) {
super(v);
t = (CardView) v.findViewById(R.id.card_view);
thumbnail = (ImageView) v.findViewById(R.id.thumbnail);
mealTitle = (TextView)v.findViewById( R.id.meal_title );
delete = (ImageView)v.findViewById( R.id.delete );
mealPrice = (TextView)v.findViewById( R.id.meal_price );
mealQuantity = (TextView)v.findViewById( R.id.meal_quantity );
}
}
}
You're getting null pointer exception because this line CustomViewHolder holder = (CustomViewHolder) view.getTag(); is giving out null. Because view.getTag() is null. This maybe because you haven't set a tag for the view using view.setTag() before your onClickListener is called.
I think you are having these code inside onBind
View.OnClickListener clickListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
CustomViewHolder holder = (CustomViewHolder) view.getTag();
int position = holder.getAdapterPosition();
//check here This is where the error os coming from
String numbers=feedItemList.get(position).toString();
feedItemList.remove(numbers);
}
};
so, I don't thing so to find position you require with creating object of CustomViewHolder
you can directly use position given in onBind() method

ListView displays arraylist data twice

Can anyone help me with figuring out why my listview repeats the results it gets from the database. I am using a Listview with Checkbox. Here is my code below.
public class AccessLevels extends Fragment {
MyAdminAdapter adminAdapter = null;
Guards guards;
ListView listView;
public ArrayList<Guards> guardsName;
public String str_name;
public boolean isAdmin;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_access_levels, container, false);
listView = (ListView)view.findViewById(R.id.list_of_guards);
return view;
}
private class MyAdminAdapter extends ArrayAdapter<Guards>{
private ArrayList<Guards> objectsList;
public MyAdminAdapter(Context context, int resource, ArrayList<Guards> objectsList) {
super(context, resource, objectsList);
this.objectsList = objectsList;
this.objectsList.addAll(objectsList);
}
private class ViewHolder{
CheckBox chk_name;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null){
LayoutInflater vi = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.single_row_access, null);
holder = new ViewHolder();
holder.chk_name = (CheckBox) convertView.findViewById(R.id.chk_guard);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
final Guards guards = objectsList.get(position);
holder.chk_name.setText(guards.getName());
holder.chk_name.setChecked(guards.isChecked());
holder.chk_name.setTag(guards);
holder.chk_name.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
CheckBox cb = (CheckBox) v;
Guards guards = (Guards) cb.getTag();
guards.setChecked(cb.isChecked());
}
});
return convertView;
}
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onDetach() {
super.onDetach();
}
}
I get the data an store it like this.
private void DisplayAllNames() {
guardsName = new ArrayList<Guards>();
ParseQuery<ParseObject> guardsQuery = ParseQuery.getQuery("Guards");
guardsQuery.whereExists("Name");
guardsQuery.orderByAscending("Name");
guardsQuery.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> list, ParseException e) {
if (e == null) {
if (list.size() > 0) {
for (int i = 0; i < list.size(); i++) {
ParseObject data = list.get(i);
str_name = data.getString("Name");
isAdmin = data.getBoolean("admin");
guards = new Guards(str_name, isAdmin);
guardsName.add(guards);
}
adminAdapter = new MyAdminAdapter(getActivity(), R.layout.single_row_access, guardsName);
listView.setAdapter(adminAdapter);
} else {
}
} else {
}
}
});
}
Thanks in advance.
Remove this line from your MyAdminAdapter's constructor:
this.objectsList.addAll(objectsList);
You are already adding your items in the previous instruction:
this.objectsList = objectsList;
In your MyAdminAdapter you are adding the data twice:
this.objectsList = objectsList;
this.objectsList.addAll(objectsList);
You just have to remove the second line.

How to remove custom listeners?

I have many ListActivity classes in my app that act pretty much the same : list with a property (TextView) on the left and a value (Button) on the right. When I press the button I want to do something like create a dialog. Because of the repetability, I decided to create a general custom ArrayAdapter like this :
public class GeneralTvBtnAdapter extends ArrayAdapter<SettingsProperty> {
private Context mContext;
private ArrayList<SettingsProperty> mProps;
private int mLayout;
private ButtonListener mListener;
public GeneralTvBtnAdapter(Context context, int tv_btn_layout, ArrayList<SettingsProperty> objects, ButtonListener listener) {
super(context, tv_btn_layout, objects);
mContext = context;
mProps = objects;
mLayout = tv_btn_layout;
mListener = listener;
}
public void updateValue (int position, String newValue) {
mProps.get(position).setValue(newValue);
notifyDataSetChanged();
}
private class ViewHolder {
TextView mName;
Button mValue;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater mInflater = LayoutInflater.from(mContext);
convertView = mInflater.inflate(mLayout, null);
holder.mName = (TextView) convertView.findViewById(R.id.prop);
holder.mValue = (Button) convertView.findViewById(R.id.value);
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.mName.setText(mProps.get(position).getName());
holder.mValue.setText(mProps.get(position).getValue());
holder.mValue.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mListener.onButtonClicked(position);
}
});
return convertView;
}
public interface ButtonListener {
void onButtonClicked (int position);
}
}
I want to know how can I remove the ButtonListeners listeners after the calling activity is destroyed.
P.S :SettingsProperty is a POJO with String name and String value and the tv_btn_layout is a layout with a TextView and a Button as described above.
if your intent is to remove your custom listener, you have to reset it to null. You can create a setter
public void setButtonListener (final ButtonListener listener) {
mListener = listener;
}
and call if from the outside with null. Just to be sure, before accessing mListener, check for null values
If your intention is not to call listener method if activity is destroyed then override your onfinish() of Activity and initialize the boolean flag.
private boolean IsActivityAlive;
#Override
protected void onDestroy() {
IsActivityAlive=true;
super.onDestroy();
}
And inside your interface method just check for boolean flag if it is false do the action required else ignore
void onButtonClicked (int position){
if(!IsActivityAlive){
//Do remaining task }
}

Categories

Resources