Null pointer on Viewholder - java

I am trying to save the state of checkboxes in my main activity rather than in my custom adapter. I have checked that the correct data is being stored in the sharedprefs and can retrieve the information successfully but when I try and mark the checkboxes on opening the app the viewholder is null. In theory I understand what the problem is but I have no clue how to fix it.
Here is the part of code from the main activity I am having issues with:
for (int i= 0; i<results.size(); i++) {
result = (Results) customAdapter.getItem(i);
if (result != null) {
String RESULT = result.getTitle();
if (sharedPref.getBoolean(result.getTitle(), false)){
Log.i("Saved", result.getTitle());
CustomAdapter.ViewHolder viewHolder = (CustomAdapter.ViewHolder) listView.getTag(i);
Log.i("viewHolder", String.valueOf(viewHolder));
viewHolder.getCheckBox().setChecked(sharedPref.getBoolean(RESULT, false));
}
}
}

You are preparing a List<Results> to pass to adapter right? First add a extra boolean variable in Results model class to represent the state of checkbox. Now at the time you prepare the list in activity, set the value of this new boolean for each item from the preference. So that your List<Results> contain state of the checkbox.

Related

How to go through a listview and get the position of a item in it WITHOUT click on it Android Studio

I want to get the position of a item in the list view and use it in a if.
Now i am going through the listview using a for loop, and i want when i find the specfic Product Id equal to the Same Product (if clause), and when i find it i use that position to update my list
for (int i = 0; i < adapterItensDoCarrinho.getCount(); i++) {
Log.d("ENTROU", "ENTROU");
Log.d("ID", String.valueOf(lsvCarrinhoCompras.getId()));
if (produtoSelecionado.getId() == adapterItensDoCarrinho.getItemId(i)) {
Log.d("ENTROU 2", "ENTROU 2");
int novaQte = itemDoCarrinho.getQtdeSelecionada();
novaQte++;
itemDoCarrinho.setNome(produtoSelecionado.getNome());
itemDoCarrinho.setQtdeSelecionada(novaQte);
itemDoCarrinho.setPrecoItemVenda(produtoSelecionado.getPrecoProduto());
adapterItensDoCarrinho.updateItemCarrinho(lsvCarrinhoCompras.getId(), itemDoCarrinho);
break;
}
else {
itemDoCarrinho.setNome(produtoSelecionado.getNome());
itemDoCarrinho.setQtdeSelecionada(qtdeProduto);
itemDoCarrinho.setPrecoItemVenda(produtoSelecionado.getPrecoProduto());
adapterItensDoCarrinho.addItemCarrinho(itemDoCarrinho);
}
}
Hope you understand it!
Your Adapter should be the one to handle this behavior. Write a public method in the Adapter class which allows you to pass in the selected product ID. Whenever the selected product ID changes in your Activity/Fragment/whatever, call the public method in the Adapter to update the product ID value. Then, in the getView() method of the Adapter, if the ID matches, perform whatever special behavior you want to have happen for the product with that ID.

Sub arraylist output repeating itself after n elements

Newbie. I'm coding a quiz app full code on Github that loads an arrayList with four arguments:
question
image (from drawables)
key answer
possible answers presented in a radioGroup (sub-arrayList)
from the strings.xml as below
...
<string name="questionOne">Who is the "Modern Love" rock star singer?</string>
<string name="answerOne">David Bowie</string>
<string-array name="celebrityOne">
<item>Jaimie Hendrix</item>
<item>David Bowie</item>
<item>Jim Morrison</item>
<item>Elvis Presley</item>
</string-array>
...
Below is how the arguments are loaded in MainActivity (The third argument is a sub-arraylist)
ArrayList<Object> arrayList = new ArrayList<>();
loaddata()
...
public void loadData() {
arrayList.add(new Quiz(getResources().getString(R.string.questionOne),
getResources().getDrawable(R.drawable.celebrity_one_image, null),
new ArrayList<>(Arrays.asList(getResources().getStringArray(R.array.celebrityOne))),
getResources().getString(R.string.answerOne)));
arrayList.add(new Quiz(getResources().getString(R.string.questionTwo),
getResources().getDrawable(R.drawable.celebrity_two_image, null),
new ArrayList<>(Arrays.asList(getResources().getStringArray(R.array.celebrityTwo))),
getResources().getString(R.string.answerTwo)));
...
}
The issue is after N iterations, the sub-arrayList starts repeating itself (See image below).
Also I think maybe the source of the problem is in the Adapter, where for each string in sub-array is assigned to a radioButton;
void createRadioButtons(String[] arrayAnswer) {
if (mRadioGroup.getChildAt(0) != null)
return;
for (int i = 0; i < arrayAnswer.length; i++) {
mRadioGroup.addView(createRadioButtonAnswerAndSetOnClickListener(arrayAnswer[i]));
}
}
RadioButton createRadioButtonAnswerAndSetOnClickListener(String string) {
RadioButton radioButton = new RadioButton(mContext);
radioButton.setText(string);
radioButton.setOnClickListener(this);
return radioButton;
}
My situation might be similar to this but I have no static fields and arrayList is initialized as new so no need to clear().
From Documentation:
The RecyclerView creates only as many view holders as are needed to display the on-screen portion of the dynamic content, plus a few extra. As the user scrolls through the list, the RecyclerView takes the off-screen views and rebinds them to the data which is scrolling onto the screen.
This means RecyclerView reuses already created view holders when you are scrolling it(that is why your data repeats), and you must repopulate views with new data. So, instead of returning from createRadioButtons method, when mRadioGroup.getChildAt(0) != null, you must change RadioButtons texts to your new data from arrayAnswer.
in your adapter just change this:
if (mRadioGroup.getChildAt(0) != null)
return;
To this:
if (mRadioGroup.getChildAt(0) != null)
mRadioGroup.removeAllViews();
At some moment your adapter, began to reuse view holders which were created at the top of the recyclerView, but it was already filled with data, so when you call return, you just leave your old data, while you need to delete it and then add new data...

Inflating views in for loop with different identity?

I am inflating layout in view in a for loop and then adding views in Array like:
ArrayList<View> views = new ArrayList();
for (Result datalist : arraylist){
View view = layoutinflater.inflate(R.layout.viewlayout, null);
/*View modification code here....
.............
.............
.............*/
views.add(view);
};
The problem is when i get views from arraylist even by index like views.get(i) it returning only last view. I want to get all views to be able to work on all views.
Here is the code where i am getting views from arrays.
for (View v : views) {
// if (insertPoint != null) {
// if (views != null) {
// if (rel_leftright != null) {
Rect scrollBounds = new Rect();
insertPoint.getHitRect(scrollBounds);
if (v.getLocalVisibleRect(scrollBounds)) {
rel_leftright.setVisibility(GONE);
} else {
rel_leftright.setVisibility(VISIBLE);
}
// }
// }
// }
}
But this code returning only working on last view in array and i need to act on all views.
Please Help me to get out of this. Thanks!!!
First I am missing something:
- Why are you trying to work with the views (/*View modification code here.... ) before you have created all of them? First craete them in the loop and the iterate over views Array and there call the modification code.
- Are you sure you don't want to pass a parent?
View view = layoutinflater.inflate(R.layout.viewlayout, null);
Even if you don't want to be attached you can call:
View view = layoutinflater.inflate(R.layout.viewlayout, parent, false);
And in general it is not possible to fill ArrayList with values and not to find them... Please log the size of datalist, then the size of views. The most probably should match.
And also please note that by the line: /*View modification code here.... not all views are created. You first need to finish the loop.

Find/Iterate through an Android CustomListView, to find selected checkboxes

I have created a custom ListView, and populated with an ArrayList of objects. It also has a checkbox, to allow the user to select certain items, and then on a button click do something with them.
My question is: How to iterate through the ListView code-side?
I've looked at the docs for ListView but can't find a method that looks as if it iterates through. Do I need to implement this in my CustomArrayAdapter??
You can use this. You shoudn't implement nothing from nessesary methods in CustomAdapter.
private void ButtonClick() {
View v;
CheckBox chBox;
for (int i = 0; i < myList.getCount(); i++) {
v = myList.getAdapter().getView(i, null, null);
chBox = (chBox) v.findViewById(R.id.checkBox);//your xml id value for checkBox.
if (chBox.isChecked()) {
doSomething();
}
}
....
}
I would not advice to use Anatol's method as this will create new views for each item. The best way to approach this would be to handle the click of the check box and update your model accordingly. Then you can do something like this:
ListAdapter adapter = myList.getAdapter();
for (int i = 0; i < adapter.getCount(); i++) {
if (adapter.getItem(i).isChecked()) {
doSomething();
}
}
Note that isChecked need to be created in your model class. Please let me know if you have any questions.

Object of main activity in result activity not properly accessing boolean variable?

I have a main class that holds two array lists of class objects. Long story short, I'm calling an activity via startActivityForResult to get a return of the position of a spinner item selection. I have two boolean variables in the main activity that basically tell the application which list is being worked with: booleans listASelected and listBSelected. If listASelected = true, then listBSelected = false and visa-versa. In the result activity I basically generate the spinner this way:
MainActivity mainAct = new MainAtivity();
Spinner dropdown = (Spinner)findViewById(R.id.mainMenu);
for(int i = 0;i<mainAct.pickThreeNumbers.size(); i++){
optionsPickThree.add(mainAct.pickThreeNumbers.get(i).getNumbers(1)+mainAct.pickThreeNumbers.get(i).getNumbers(2)+mainAct.pickThreeNumbers.get(i).getNumbers(3));
}
for(int r = 0; r<mainAct.pickFourNumbers.size();r++){
optionsPickFour.add(mainAct.pickFourNumbers.get(r).getNumbers(1)+mainAct.pickFourNumbers.get(r).getNumbers(2)+mainAct.pickFourNumbers.get(r).getNumbers(3)+mainAct.pickFourNumbers.get(r).getNumbers(4));
}
if(mainAct.pickThreeSelected){
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, optionsPickThree);
}else{
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, optionsPickFour);
}
dropdown.setAdapter(adapter);
Then, I use this to do my setResult.
Intent output = new Intent();
if(mainAct.pickThreeSelected){
output.putExtra("slot", position);
output.putExtra("list", "PickThree");
}else{
output.putExtra("slot", position);
output.putExtra("list", "PickFour");
}
setResult(1,output);
finish();
}
The issue is that nomatter what it always works as if mainAct.pickThreeSelected = true, even if I know it is false because other sections of the app are functioning properly. What I assume is happening is that the class object is accessing the variable's initialized values instead of their current values at the time of execution. That, or I'm an idiot and there's a different way to accomplish this.
Any help, fellas? Thanks in advance!
Make pickThreeSelected as static. That way you will update the same instance everytime.
What is the default value that you have set to the mainAct.pickThreeSelected??If its true,make it as false.Then if user selects the listA change the value to true.

Categories

Resources