Observable/Observer Android - java

EDIT please see Observer Observables implementing issue - It seems I was overriding methods that didn't need to be and not calling setChanged(); before notify();
I've been reading up on the Observer Pattern for keeping my UI up to date but I still can't see the use for it.. Even if in my particular object notifies my MainActivity then runs the update(); method I still wouldn't be able to use the Pet object to pull the update values as the object is created in Oncreate...and I just can't create a new object because then the variables will be different..this is my implementation and it doesn't seem to work.
Observer/MainActivity
package com.grim.droidchi;
import java.util.Observable;
import java.util.Observer;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.WebSettings.LayoutAlgorithm;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements Observer, OnClickListener {
private static final String TAG = "VPET";
private static final String APP_PREFS = "VPET";
private static final int REQUEST_CODE = 1;
Boolean isAlive = false;
TextView happiness_display, health_display, hunger_display, level_display;
Button PunchPet, UpdateHunger;
public static Pet pet = new Renamon();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SharedPreferences settings = getSharedPreferences("APP_PREFS",
MODE_PRIVATE);
WebView myWebView = (WebView) findViewById(R.id.pet_display);
myWebView.loadUrl("file:///android_asset/renamon.gif");
myWebView.setInitialScale(10000);
myWebView.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);
PunchPet = (Button) findViewById(R.id.PunchPet);
UpdateHunger = (Button) findViewById(R.id.UpdateHunger);
final TextView hunger_display = (TextView) findViewById(R.id.hunger_display);
TextView happiness_display = (TextView) findViewById(R.id.happiness_display);
TextView level_display = (TextView) findViewById(R.id.level_display);
TextView health_display = (TextView) findViewById(R.id.health_display);
hunger_display.setText(Integer.toString(pet.getHunger()));
health_display.setText(Integer.toString(pet.getHP()));
level_display.setText(Integer.toString(pet.getLVL()));
happiness_display.setText(Integer.toString(pet.getHappy()));
Intent intent = new Intent(this, Gameloop.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
getBaseContext(), REQUEST_CODE, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + (5 * 1000), 1800000, pendingIntent);
// 1800000 ms = 30 mins
pet.feed();
pet.addObserver(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
#Override
protected void onPause() {
super.onPause();
}
#Override
public void update(Observable o, Object data) {
hunger_display.setText(Integer.toString(pet.getHunger()));
health_display.setText(Integer.toString(pet.getHP()));
level_display.setText(Integer.toString(pet.getLVL()));
happiness_display.setText(Integer.toString(pet.getHappy()));
Log.d(TAG, "UPDATED FROM OBSERVER");
}
#Override
public void onClick(View v) {
if (v == PunchPet) {
pet.setHP(500);
Toast.makeText(getApplicationContext(), "PUNCHPET", Toast.LENGTH_SHORT).show();
health_display.setText(Integer.toString(pet.getHP()));
}else {
}
}
}
Observable/Pet
package com.grim.droidchi;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import android.util.Log;
public class Pet extends Observable implements PetInterface {
protected Set<Observer> observers;
private static final String TAG = "VPET";
private int Health = 100;
#Override
public void addObserver(Observer o) {
observers.add(o);
super.addObserver(o);
}
#Override
public void notifyObservers() {
observers.notify();
super.notifyObservers();
}
#Override
public synchronized void deleteObserver(Observer o) {
observers.remove(o);
super.deleteObserver(o);
}
private int Happiness = 10;
private int Level = 1;
private int Hunger = 0;
private int Exp = 0;
private String Name;
private Boolean isAlive = true;
private Boolean isSick = false;
public void setHP(int hp) {
this.Health = hp;
notifyObservers(hp);
}
public void setLVL(int lvl) {
this.Level = lvl;
notifyObservers(lvl);
}
public void setXP(int xp) {
this.Exp = xp;
notifyObservers(xp);
}
public void setHunger(int hunger) {
this.Hunger = hunger;
notifyObservers(hunger);
}
public void setHappy(int happy) {
this.Happiness = happy;
notifyObservers(happy);
}
public int getHP() {
return Health;
}
public int getLVL() {
return Level;
}
public int getXP() {
return Exp;
}
public int getHunger() {
return Hunger;
}
public int getHappy() {
return Happiness;
}
public boolean isAlive() {
return isAlive;
}
public boolean isSick() {
return isSick;
}
#Override
public void sleep() {
// TODO Auto-generated method stub
}
#Override
public void clean() {
// TODO Auto-generated method stub
}
#Override
public void feed() {
Log.d(TAG, "FEEDING FROM INTERFACE THING");
}
#Override
public void passtime() {
}
}

First, I wouldn't recommend overriding addObserver or removeObserver in your observable object. The API does a really good job of implementing this (unless you want some specific functionality).
Second, the method notifyObservers() is overloaded so that you can pass it an object, IE notifyObservers(Object obj). If you pass it your Pet, notifyObservers(this), then you will have a reference to your Pet object that is being observed.
I think this is your question but please correct me if I am wrong.
EDIT: To clarify, my answer is contingent upon you using the Observable class in the Java API here.
Upon further review, you should already have a reference to the Pet object that called the update method of the Observer

Your pet is not accessible in other methods because its not defined at global level.
You should define Pet pet = new Renamon(); outside of onCreate method.

Related

Index out of Bound on Item deletion in a Recycler View's adapter

I am trying to create a note-taking app focusing on color-changing.
In one of the activity, I am trying to implement item addition and deletion to the note
picture_of_the_activity.
Item addition obviously works as intended.
The problem is with the deletion, it is very inconsistent: when I delete all the item starting from the last one upward, everything work fine; if I delete items in another order the adapter mess up, do not always delete the correct one and crashes when removing the last item.
I looked it up and found some possible solution (here or in other websites) but couldn't find a solution, or, so I thought.
I created methods inside the adapter addItem() and removeItem() so any changes is done within the class.
Maybe I am misunderstanding a concept or missing something?
Thank you in advance!
some interfaces or protion of the code are missing because I didn't implement some features yet
Activity Code
package com.example.colornoteplus;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;
public class CheckListNoteActivity extends AppCompatActivity{
// note editable views
private EditText titleView;
private TextView titleCharacterCount;
private ImageButton colorView;
private RecyclerView contentView;
private FloatingActionButton fab;
CheckListAdapter adapter;
// toolbar
private Toolbar toolbar;
// Current note
private CheckListNote note;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getNoteFromIntent();
note.getContent().add(new CheckListItem("ONE"));
note.getContent().add(new CheckListItem("TWO"));
note.getContent().add(new CheckListItem("THREE"));
note.getContent().add(new CheckListItem("FOUR"));
note.getContent().add(new CheckListItem("FIVE"));
changeViewsColor(0);
}
// Method used to add menus and configure button action
// like OnClickListeners ...
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Create a submenu for sorting purpose
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_check_list_activity,menu);
return super.onCreateOptionsMenu(menu);
}
// get note from the intent
private void getNoteFromIntent(){
if (!getIntent().getStringExtra(Statics.KEY_NOTE_ACTIVITY).equals(Statics.NOTE_DEFAULT_UID)){
note = MySharedPreferences.LoadCheckListNoteFromSharedPreferences(getIntent().getStringExtra(Statics.KEY_NOTE_ACTIVITY),getApplicationContext());
} else {
note = new CheckListNote();
}
}
private void changeViewsColor(int color){
// set the global theme
setTheme(StyleManager.getTheme(color));
// set the appropriate layout
setContentView(R.layout.activity_check_list_note);
// change status bar color
getWindow().setStatusBarColor(getResources().getColor(StyleManager.getThemeColor(color)));
// set up FAB action
fab = findViewById(R.id.fab_add_item);
fab.setOnClickListener(view -> onFabClickListener());
// setting the toolbar
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setBackgroundColor(getResources().getColor(StyleManager.getThemeColor(color)));
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
// setting the note title
titleView = findViewById(R.id.note_title_view);
titleView.setText("");
titleView.setTextColor(getResources().getColor(StyleManager.getThemeColorDark(color)));
titleView.setHintTextColor(getResources().getColor(StyleManager.getThemeColorLight(color)));
// setting the character counter for the note title
titleCharacterCount = findViewById(R.id.note_title_characters);
String m = titleView.getText().toString().trim().length()+ getString(R.string.text_divider)+ getResources().getInteger(R.integer.title_max_length);
titleCharacterCount.setText(m);
titleCharacterCount.setTextColor(getResources().getColor(StyleManager.getThemeColor(color)));
titleView.addTextChangedListener(new TextWatcher()
{
#Override
public void onTextChanged(CharSequence s, int start, int before, int count)
{
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int aft)
{
}
#Override
public void afterTextChanged(Editable s)
{
// this will show characters remaining
String msg = titleView.getText().toString().length()+ getString(R.string.text_divider)+ getResources().getInteger(R.integer.title_max_length);
titleCharacterCount.setText(msg);
}
});
// setting the color view
colorView = findViewById(R.id.note_color_view);
colorView.setOnClickListener(view -> buildColorPickDialog());
colorView.setBackgroundResource(StyleManager.getBackground(color));
adapter = new CheckListAdapter(getApplicationContext(),note.getContent(),color);
adapter.setOnItemClickListener(new CheckListAdapter.OnItemClickListener() {
#Override
public void onChecked(int position) {
Toast.makeText(CheckListNoteActivity.this, "Checked item: " +position, Toast.LENGTH_SHORT).show();
}
#Override
public void onUnchecked(int position) {
Toast.makeText(CheckListNoteActivity.this, "Unchecked item: " +position, Toast.LENGTH_SHORT).show();
}
#Override
public void onSetPriority(int position) {
}
#Override
public void onSetReminder(int position) {
}
#Override
public void onDelete(int position) {
adapter.removeItem(position);
Toast.makeText(CheckListNoteActivity.this, "List has "+note.getContent().size()+" elements", Toast.LENGTH_SHORT).show();
}
});
contentView = findViewById(R.id.note_content_view);
contentView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
contentView.setAdapter(adapter);
}
private void switchColor(int color){
String tempTitle = titleView.getText().toString().trim();
changeViewsColor(color);
titleView.setText(tempTitle);
}
// build the color picker dialog
private void buildColorPickDialog(){
FragmentPickColor fragment = new FragmentPickColor(new ColorAdapter(),5,note.getColor());
fragment.show(getSupportFragmentManager(),Statics.TAG_FRAGMENT_COLOR_PICK);
fragment.setOnItemClickListener(new ColorAdapter.OnItemClickListener() {
#Override
public void OnClickListener(int position) {
note.setColor(position);
switchColor(position);
fragment.dismiss();
}
#Override
public void OnLongClickListener(int position) {
}
});
}
private void onFabClickListener(){
FragmentAddCheckListItem fragment = new FragmentAddCheckListItem(note.getColor());
fragment.show(getSupportFragmentManager(),Statics.TAG_FRAGMENT_ADD_CHECK_LIST_ITEM);
fragment.setOnClickListener(new FragmentAddCheckListItem.OnClickListener() {
#Override
public void onConfirmClickListener() {
fragment.getItem().setDescription(fragment.getInputText());
adapter.addItem(fragment.getItem(),0);
fragment.dismiss();
}
#Override
public void onSetPriorityClickListener() {
}
#Override
public void onSetDueTimeClickListener() {
FragmentDatePicker datePicker = new FragmentDatePicker();
datePicker.show(getSupportFragmentManager(),Statics.TAG_FRAGMENT_DATE_PICKER);
datePicker.setOnDateSet((year, month, day) -> {
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR,year);
c.set(Calendar.MONTH,month);
c.set(Calendar.DAY_OF_MONTH,day);
fragment.getItem().setDueDate(c.getTime().getTime());
fragment.setDueTimeText(DateFormat.getDateInstance().format(new Date(fragment.getItem().getDueDate())));
});
}
});
}
}
Adapter
package com.example.colornoteplus;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.RecyclerView;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
public class CheckListAdapter extends RecyclerView.Adapter<CheckListAdapter.MyViewHolder> {
public CheckListAdapter(Context context,ArrayList<CheckListItem> list, int color) {
this.list = list;
this.color = color;
this.context = context;
}
final private ArrayList<CheckListItem> list;
final private int color;
final private Context context;
private OnItemClickListener listener;
#NonNull
#Override
public CheckListAdapter.MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new CheckListAdapter.MyViewHolder(LayoutInflater.
from(parent.getContext()).
inflate(R.layout.item_check_list,parent,false));
}
#Override
public void onBindViewHolder(#NonNull CheckListAdapter.MyViewHolder holder, int position) {
CheckListItem currentItem = list.get(position);
holder.background.setBackgroundResource(StyleManager.getBackgroundLight(color));
holder.checkBox.setOnCheckedChangeListener((compoundButton, b) -> {
if (b) listener.onChecked(position);
else listener.onUnchecked(position);
});
holder.title.setTextColor(context.getResources().getColor(StyleManager.getThemeColorDark(color)));
holder.title.setHintTextColor(context.getResources().getColor(StyleManager.getThemeColor(color)));
assert currentItem != null;
holder.title.setText(currentItem.getDescription().trim());
holder.dueTimeText.setTextColor(context.getResources().getColor(StyleManager.getThemeColor(color)));
holder.dueTimeText.setText(currentItem.getDoneDate() != -1 ? DateFormat.getDateInstance().format(new Date(currentItem.getDueDate())) : context.getString(R.string.set_reminder));
holder.dueTimeText.setOnClickListener(view -> listener.onSetReminder(position));
holder.priorityText.setTextColor(context.getResources().getColor(StyleManager.getThemeColor(color)));
holder.priorityText.setText(currentItem.priorityToString(context));
holder.priorityText.setOnClickListener(view -> listener.onSetPriority(position));
holder.delete.setBackgroundResource(StyleManager.getBackground(color));
holder.delete.setOnClickListener(view -> {
// listener.onDelete(position);
removeItem(position);
});
}
#Override
public int getItemCount() {
return list.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder{
CheckBox checkBox;
ConstraintLayout background;
EditText title;
ImageButton delete;
TextView priorityText,dueTimeText;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
checkBox = itemView.findViewById(R.id.item_check_box);
title = itemView.findViewById(R.id.item_title);
dueTimeText = itemView.findViewById(R.id.item_due_time_text);
priorityText = itemView.findViewById(R.id.item_priority_text);
delete = itemView.findViewById(R.id.item_delete);
background = itemView.findViewById(R.id.item_background);
}
}
public void addItem(CheckListItem item,int position){
if (position < 0){
list.add(item);
notifyItemInserted(list.size()-1);
}
else {
list.add(position,item);
notifyItemInserted(position);
}
}
public void removeItem(int position){
list.remove(position);
notifyItemRemoved(position);
}
public void setOnItemClickListener(OnItemClickListener listener){
this.listener = listener;
}
public interface OnItemClickListener{
void onChecked(int position);
void onUnchecked(int position);
void onSetPriority(int position);
void onSetReminder(int position);
void onDelete(int position);
}
}
public void addItem(CheckListItem item, int position) {
if (position >= 0) {
list.add(position, item);
notifyItemInserted(position);
}
}
public void removeItem(int position) {
if (position >= 0) {
list.remove(position);
notifyItemRemoved(position);
}
}
And in onBindViewHolder use holder.getAdapterPosition() instead of position in your listeners like this:
holder.delete.setOnClickListener(view -> {
// listener.onDelete(position);
removeItem(holder.getAdapterPosition());
});

Multiple AutoCompleteTextView in fragment

I am trying to add a second AutoCompleteTextView (that gets objects from a Web API) in a fragment, but it never retrieves anything.
Currently testing on an Emulator, on API level 24. I have previously tried the code for this AutoCompleteTextView in another activity and it worked as intended there.
Fragment Code
package com.advatek.timewin.fragments;
import android.app.AlertDialog;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v7.widget.AppCompatAutoCompleteTextView;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.TextView;
import com.advatek.timewin.MainActivity;
import com.advatek.timewin.R;
import com.advatek.timewin.helper.APICall;
import com.advatek.timewin.helper.APIHelper;
import com.advatek.timewin.helper.AutoSuggestAdapter;
import com.advatek.timewin.helper.JSONHelper;
import com.advatek.timewin.helper.JobSuggestAdapter;
import com.advatek.timewin.models.Employee;
import com.advatek.timewin.models.Function;
import com.advatek.timewin.models.PayPeriod;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import org.json.JSONArray;
import org.json.JSONException;
import java.util.ArrayList;
import java.util.List;
/**
* A simple {#link Fragment} subclass.
* Activities that contain this fragment must implement the
* {#link Clock.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {#link Clock#newInstance} factory method to
* create an instance of this fragment.
*/
public class Clock extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private Context context;
Handler handler;
Handler jobHandler;
AppCompatAutoCompleteTextView txtEmpSearch;
AppCompatAutoCompleteTextView txtJobSearch;
AutoSuggestAdapter autoAdapter;
JobSuggestAdapter jobAdapter;
private static final int TRIGGER_AUTO_COMPLETE = 100;
private static final long AUTO_COMPLETE_DELAY = 300;
private static List<Function> functionList;
PayPeriod period;
private TextView txtPayWeek;
Spinner spnJobs;
Button btnSignIn;
private OnFragmentInteractionListener mListener;
public Clock() {
// Required empty public constructor
}
public AppCompatAutoCompleteTextView getTextView(){
return txtEmpSearch;
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment Clock.
*/
// TODO: Rename and change types and number of parameters
public static Clock newInstance(String param1, String param2) {
Clock fragment = new Clock();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
context = getContext();
period = new PayPeriod();
functionList = new ArrayList<>();
try{
WeekTask wTask = new WeekTask();
wTask.execute().get();
// JobTask task = new JobTask();
// task.execute();
txtJobSearch = (AppCompatAutoCompleteTextView)getView().findViewById(R.id.txtEmpLookup);
jobAdapter = new JobSuggestAdapter(context, R.layout.support_simple_spinner_dropdown_item);
txtJobSearch.setThreshold(2);
txtJobSearch.setAdapter(jobAdapter);
// Fires when an Employee is selected
txtJobSearch.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
InputMethodManager in = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
in.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0);
Function job = (Function) parent.getItemAtPosition(position);
((MainActivity)getActivity()).setJob(job);
}
});
txtJobSearch.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
jobHandler.removeMessages(TRIGGER_AUTO_COMPLETE);
jobHandler.sendEmptyMessageDelayed(TRIGGER_AUTO_COMPLETE, AUTO_COMPLETE_DELAY);
}
#Override
public void afterTextChanged(Editable s) {
if(txtJobSearch.getText().toString().equals("")){
}
}
});
jobHandler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
if (msg.what == TRIGGER_AUTO_COMPLETE) {
if (!TextUtils.isEmpty(txtJobSearch.getText())) {
getJobs(txtJobSearch.getText().toString());
}
}
return false;
}
});
}
catch (Exception ex){
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
dialog.setTitle("Error");
dialog.setMessage(ex.getMessage());
dialog.show();
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_clock, container, false);
txtEmpSearch = view.findViewById(R.id.txtEmpLookup);
txtJobSearch = view.findViewById(R.id.txtJobSearch);
btnSignIn = view.findViewById(R.id.btnSignIn);
return inflater.inflate(R.layout.fragment_clock, container, false);
}
/**
* Gets the Current Pay Period and Sets up the AutoCompleteTextView
*/
private class WeekTask extends AsyncTask<PayPeriod, Void, PayPeriod>{
#Override
protected PayPeriod doInBackground(PayPeriod... payPeriods) {
return new APIHelper().getCurrentPayWeek(JSONHelper.getDateAsInt());
}
#Override
protected void onPostExecute(PayPeriod payPeriod) {
period = payPeriod;
txtPayWeek = getView().findViewById(R.id.txtPayWeekNo);
txtPayWeek.setText(getString(R.string.txtCurrentWeek, payPeriod.getPayWeekNo()));
txtEmpSearch = (AppCompatAutoCompleteTextView) getView().findViewById(R.id.txtEmpLookup);
autoAdapter = new AutoSuggestAdapter(context, R.layout.support_simple_spinner_dropdown_item);
txtEmpSearch.setThreshold(2);
txtEmpSearch.setAdapter(autoAdapter);
// Fires when an Employee is selected
txtEmpSearch.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
InputMethodManager in = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
in.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0);
Employee emp = (Employee) parent.getItemAtPosition(position);
((MainActivity)getActivity()).setEmployee(emp);
}
});
txtEmpSearch.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
handler.removeMessages(TRIGGER_AUTO_COMPLETE);
handler.sendEmptyMessageDelayed(TRIGGER_AUTO_COMPLETE, AUTO_COMPLETE_DELAY);
}
#Override
public void afterTextChanged(Editable s) {
if(txtEmpSearch.getText().toString().equals("")){
}
}
});
handler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
if (msg.what == TRIGGER_AUTO_COMPLETE) {
if (!TextUtils.isEmpty(txtEmpSearch.getText())) {
makeApiCall(txtEmpSearch.getText().toString());
}
}
return false;
}
});
}
}
private void getJobs(String term){
APICall.getJobsByPartial(context, term, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
List<Function> jobs = new ArrayList<>();
try{
JSONArray array = new JSONArray(response);
jobs = new APIHelper().populateFunctionList(array);
jobAdapter.setData(jobs);
jobAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
}
}
The code above does work, the issue was with how I was testing it. I had to use the first AutoCompleteTextView, pick a suggestion, then use the second one. If I tried to use the second one first, it does not work.

How to add text to TextView from Loader

Now I'm studying Threads and my task is to make a counter, which will add number from 0 to 9 to TextView with the help of Loader. Of course, I know that it isn't the best variant to use Loader for such tasks, but I'd like to understand how does it work.
So, I have the following code:
package asus.example.com.exercise4;
import android.annotation.SuppressLint;
import android.content.Context;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class LoaderActivity extends AppCompatActivity {
private TextView counter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_threads);
Button startButton = findViewById(R.id.start_button);
Button cancelButton = findViewById(R.id.cancel_button);
startButton.setOnClickListener(listener);
cancelButton.setOnClickListener(listener);
counter = findViewById(R.id.counter);
}
private View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
switch (v.getId()){
case R.id.start_button:
getSupportLoaderManager().initLoader(0, null, new LoaderClass());
break;
case R.id.cancel_button:
break;
}
}
};
#SuppressLint("StaticFieldLeak")
class AsyncTaskLoaderClass extends AsyncTaskLoader<Void>{
AsyncTaskLoaderClass(#NonNull Context context) {
super(context);
}
#Nullable
#Override
public Void loadInBackground() {
for (int i = 0; i<10;i++){
counter.setText(i);
SystemClock.sleep(500);
}
return null;
}
}
private class LoaderClass implements LoaderManager.LoaderCallbacks<Void>{
#NonNull
#Override
public Loader<Void> onCreateLoader(int i, #Nullable Bundle bundle) {
return new LoaderActivity.AsyncTaskLoaderClass(LoaderActivity.this);
}
#SuppressLint("SetTextI18n")
#Override
public void onLoadFinished(#NonNull Loader<Void> loader, Void aVoid) {
counter.setText("Done!");
}
#Override
public void onLoaderReset(#NonNull Loader<Void> loader) {
}
}
}
When I run the project I have a runtime error:
java.lang.IllegalArgumentException: Object returned from onCreateLoader must not be a non-static inner member class: AsyncTaskLoaderClass{eed39bf id=0}
Yes, I understand, that it means that AsyncTaskLoaderClass should be in another file or static, but in such case I won't have an opportunity to add text to textview. So, how can I solve this problem?
UPD
I changed the code in clicking start button in such way:
case R.id.start_button:
Loader loader = getSupportLoaderManager().initLoader(0, null, LoaderActivity.this);
loader.forceLoad();
Log.i(TAG, "Button start clicked");
break;
And now each time in the loop I have the following error:
E/e.com.exercise: Invalid ID 0x00000009.
E/EventBus: Could not dispatch event: class asus.example.com.exercise4.LoaderActivity$MyAsyncTaskLoader$ProgressEvent to subscribing class class asus.example.com.exercise4.LoaderActivity
android.content.res.Resources$NotFoundException: String resource ID #0x9
UPD 2
Finally fixed the problem in the following way:
Was
counter.setText(i);
Now
counter.setText(""+i);
Probably I don't understrand why it works, but it works
Make the Activity implement LoaderCallbacks. Also a Loader retrieves one particular value in its onLoadFinished callback, and it should return the retrieved (loaded) item as a result.
To change what value is being loaded by a Loader, you're supposed to restart the loader with a new argument bundle, and pass in the parameters so that it knows what it is doing.
Then again, you are trying to create something like "publishProgress" in AsyncTask; Loaders cannot do that out of the box, and need some variant of "sending an event" (handler threads if you are adventurous, but most likely an event bus, see implementation 'org.greenrobot:eventbus:3.1.1').
TL;DR: use EventBus for this.
public class LoaderActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Void> {
private TextView counter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_threads);
Button startButton = findViewById(R.id.start_button);
Button cancelButton = findViewById(R.id.cancel_button);
counter = findViewById(R.id.counter);
startButton.setOnClickListener((view) -> {
getSupportLoaderManager().initLoader(0, null, LoaderActivity.this);
});
cancelButton.setOnClickListener((view) -> {
// do nothing, apparently
});
EventBus.getDefault().register(this);
}
#Override
protected void onDestroy() {
EventBus.getDefault().unregister(this);
super.onDestroy();
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onLoaderProgressEvent(MyAsyncTaskLoader.ProgressEvent event) {
counter.setText("" + event.getNumber());
}
#NonNull
#Override
public Loader<Void> onCreateLoader(int i, #Nullable Bundle bundle) {
return new MyAsyncTaskLoader(LoaderActivity.this);
}
#SuppressLint("SetTextI18n")
#Override
public void onLoadFinished(#NonNull Loader<Void> loader, Void aVoid) {
counter.setText("Done!");
}
#Override
public void onLoaderReset(#NonNull Loader<Void> loader) {
}
public static class MyAsyncTaskLoader extends AsyncTaskLoader<Void> {
public static class ProgressEvent {
private final int number;
public ProgressEvent(int number) {
this.number = number;
}
public int getNumber() { return number; }
}
public MyAsyncTaskLoader(#NonNull Context context) {
super(context);
}
#Nullable
#Override
public Void loadInBackground() {
for (int i = 0; i<10;i++){
EventBus.getDefault().post(new ProgressEvent(i));
SystemClock.sleep(500);
}
return null;
}
}
}
Your are using inner AsyncTaskLoaderClass in Activity class. Inner class holds the reference of Outer class. That means your AsyncTaskLoaderClass may hold Activity reference in some cases. Make your inner class static.
You have 2 solutions. Make AsyncTaskLoaderClass a separate class file or make AsyncTaskLoaderClass a static class.
make textview public static like this public static TextView counter;

Can't access ArrayAdapter from AlertDialog

TL;DR
I don't understand how to change my ArrayList dataset from a dialog so that it updates my listview. My current solution crashes because the ListView doesn't update. Need to know where my code is going wrong.
The Problem
I have one activity that has a ListView of items with an ArrayAdapter that connects it to my data (ArrayList). When a user clicks on an item in that list I load an AlertDialog that allows the user to delete that item. Debugging shows that the item does get removed from the data, the dialog closes as expected but the ListView doesn't update and subsequent clicks cause the app to crash.
The problem seems to be tied to the itemsList.notifyDataSetChanged();. I've tried hitting the adapter instead but then the Adapter itself can't be resolved.
I know this is due to an error on my part but I can't find where I'm going wrong.
The Code
ScannerActivity.java
import android.content.Intent;
import android.graphics.pdf.PdfDocument;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
public class ScannerActivity extends AppCompatActivity {
Button delete, deleteAll, manual, export, newPull;
EditText input_main;
static int pulls = 001;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scanner);
//Load some items for testing
final PullSheet pullSheet = new PullSheet();
pullSheet.createSheet(nameText, roleText, storeText, runitText);
pullSheet.addItem("12543", 5);
pullSheet.addItem("3526", 1);
pullSheet.addItem("00045", 3);
pullSheet.addItem("95462", 18);
pullSheet.addItem("1181", 53);
pullSheet.addItem("6543", 1);
final ArrayAdapter<PullItem> itemAdapter =
new ArrayAdapter<PullItem>(this, 0, pullSheet.SheetItems) {
#Override
public View getView(int position,
View convertView,
ViewGroup parent){
PullItem currentItem = getItem(position);//
if(convertView == null) {
convertView = getLayoutInflater()
.inflate(R.layout.item, null, false);
}
TextView itemSku =
(TextView)convertView.findViewById(R.id.item_sku);
TextView itemQty =
(TextView)convertView.findViewById(R.id.item_qty);
itemSku.setText(currentItem.sku);
itemQty.setText(String.valueOf(currentItem.qty));
return convertView;
}
};
final ListView itemsList = (ListView) findViewById(R.id.itemsList);
itemsList.setAdapter(itemAdapter);
itemsList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(final AdapterView<?> itemAdapter,
View view, int position, long rowId) {
final PullItem item = pullSheet.SheetItems.get(position);
final PullSheet sheet = pullSheet;
//load dialog
final AlertDialog.Builder mBuilder = new AlertDialog.Builder(ScannerActivity.this);
final View mView = getLayoutInflater().inflate(R.layout.dialog_interact, null);
//Declare dialog ui elements
Button mYes = (Button) mView.findViewById(R.id.btnYes);
Button mNo = (Button) mView.findViewById(R.id.btnNo);
TextView skuData = (TextView) mView.findViewById(R.id.skuData);
TextView qtyData = (TextView) mView.findViewById(R.id.qtyData);
skuData.setText(item.sku);
qtyData.setText(item.qty.toString());
mBuilder.setView(mView);
final AlertDialog dialog = mBuilder.create();
dialog.show();
mYes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
deletePullItem(sheet, item);
itemsList.notifyDataSetChanged();// This isn't working, "Cannot resolve method notifyDataSetChanged()"
dialog.dismiss();
}
});
mNo.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
}
});
}
public void deletePullItem(PullSheet sheet, PullItem item)
{
sheet.removeItem(item);
}
}
PullSheet.java
import java.sql.Time;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.UUID;
public class PullSheet extends Application{
protected String pullerName;
protected String role;
protected String store;
protected String sheetId;
protected String runItId;
protected Long startTime = System.currentTimeMillis();
protected ArrayList<PullItem> SheetItems = new ArrayList<PullItem>();
public void createSheet(String _pullerName, String _role, String _store, String _runItId){
setPullerName(_pullerName);
setRole(_role);
setStore(_store);
setRunItId(_runItId);
setSheetId();
}
protected void addItem(String sku, Integer qty){
SheetItems.add(new PullItem(sku, qty));
}
protected void removeItem(PullItem item){
this.SheetItems.remove(item);
}
//Getters and setters
public String getPullerName(){ return pullerName; }
public String getRole(){
return role;
}
public String getStore(){
return store;
}
public String getRunItId(){
return runItId;
}
public String getSheetId(){
return sheetId;
}
public Long getStartTime(){
return startTime;
}
private void setPullerName(String _pullerName){ pullerName = _pullerName; }
private void setRole(String _role){ pullerName = _role; }
private void setStore(String _store){ store = _store; }
private void setRunItId(String _runItId){ runItId = _runItId; }
private void setSheetId(){
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
String dateString = formatter.format(new Date(startTime));
UUID uuid = UUID.randomUUID();
String randUUID = uuid.toString();
sheetId = dateString + "-" + this.pullerName + "-" + randUUID + "-" + runItId;
}
}
PullItem.java
public class PullItem {
protected String sku;
protected Integer qty;
public PullItem(String sku, Integer qty) {
setSku(sku);
this.qty = 1;
}
String getSku(){ return sku; }
Integer getQty(){ return qty; }
void setSku(String _sku){ sku = _sku; }
void setQty(Integer _qty){ qty = _qty; }
void incrementQty(){ qty += 1; }
}
The Solution
I need to be told where I'm going wrong. I know it has to do with the ArrayAdapter and the ListView, but Everything I've tried just moves the "Can't resolve" to another part of the expression.
Thanks in advance for any help
notifyDatasetChanged() is an Adapter method, so you can't use it with ListView
But this should work:
Make your Adapter a member variable (instantiate it the way you did) so you can access it everywhere in the Activity:
private ArrayAdapter<PullItem> itemAdapter;
Simply call deletePullItem() if the user clicks the OK-Button:
mYes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
deletePullItem(sheet, item);
dialog.dismiss();
}
});
And call notifyDatasetChanged() when really deleting the item:
public void deletePullItem(PullSheet sheet, PullItem item)
{
sheet.removeItem(item);
itemAdapter.notifyDatasetChanged();
}
Try this:
mYes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
deletePullItem(sheet, item);
itemsList.getAdapter().notifyDataSetChanged();
dialog.dismiss();
}
});

Edittext data appears in other edittext scrolling in recyclerview [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm a newbie coding witch android studio and I try to save data on editText inside a recyclerview but data disappear or is duplicated in another editText.
Could someone help me please ?
Here is my code :
TaskActivity.java
package com.example.davidsimon.appexploit.activities;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.opengl.EGLDisplay;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.example.davidsimon.appexploit.R;
import com.example.davidsimon.appexploit.classes.ReturnResponse;
import com.example.davidsimon.appexploit.classes.Task;
import com.example.davidsimon.appexploit.classes.TaskAdapter;
import com.example.davidsimon.appexploit.classes.TaskToSend;
import com.example.davidsimon.appexploit.classes.User;
import com.example.davidsimon.appexploit.services.JsonService;
import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.appindexing.Thing;
import com.google.android.gms.common.api.GoogleApiClient;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import static android.R.attr.button;
import static android.R.attr.title;
public class TasksActivity extends AppCompatActivity {
private List<Task> taskList = new ArrayList<>();
private RecyclerView recyclerView;
public TaskAdapter mAdapter;
Button GoPhoto;
String user;
JsonService service;
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tasks);
Button uploadButton = (Button) findViewById(R.id.butUpload);
GoPhoto = (Button) findViewById(R.id.butt_photo);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(getString(R.string.base_url))
.addConverterFactory(GsonConverterFactory.create())
.build();
service = retrofit.create(JsonService.class);
Button takePictureButton = (Button) findViewById(R.id.butt_photo);
user = getIntent().getStringExtra("user");
//imageView = (ImageView) findViewById(R.id.imageview);
uploadButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
TaskToSend task;
List<TaskToSend> listTask = new ArrayList<>();
for (int i = 0; i < mAdapter.getItemCount(); i++) {
task = new TaskToSend(mAdapter.getItem(i).getTitle(), String.valueOf(mAdapter.getItem(i).isState()), mAdapter.getItem(i).getComment(), user);
if (task.getState() == "true") {
task.setState("Fait");
} else {
task.setState("Non fait");
}
listTask.add(task);
}
service.saveTasks(listTask).enqueue(new Callback<ReturnResponse>() {
#Override
public void onResponse(Call<ReturnResponse> call, Response<ReturnResponse> response) {
Log.wtf("Fichier", "RĂ©ponse");
}
#Override
public void onFailure(Call<ReturnResponse> call, Throwable t) {
Log.wtf("Fichier", "Pas de réponse");
}
});
Intent TakstoUpload = new Intent(TasksActivity.this, UploadActivity.class);
startActivity(TakstoUpload);
}
});
takePictureButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 0);
}
});
service.getTasks().enqueue(new Callback<List<Task>>() {
#Override
public void onResponse(Call<List<Task>> call, Response<List<Task>> response) {
List<Task> listeTaches = response.body();
Log.wtf("Nombre de taches", "Nombre de taches : " + listeTaches.size());
Calendar c = Calendar.getInstance();
int DayOfWeek = c.get(Calendar.DAY_OF_WEEK);
for (Task t : listeTaches) {
if (t.getPeriod()== DayOfWeek || t.getPeriod()== 0) {
taskList.add(t);
}
}
displayRecyclerView();
}
#Override
public void onFailure(Call<List<Task>> call, Throwable t) {
Log.wtf("GetTasks Failure", t.toString());
}
});
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
public void displayRecyclerView() {
recyclerView = (RecyclerView) findViewById(R.id.tasks_recycler_view);
mAdapter = new TaskAdapter(taskList);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
}
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
public Action getIndexApiAction() {
Thing object = new Thing.Builder()
.setName("Tasks Page") // TODO: Define a title for the content shown.
// TODO: Make sure this auto-generated URL is correct.
.setUrl(Uri.parse("http://[ENTER-YOUR-URL-HERE]"))
.build();
return new Action.Builder(Action.TYPE_VIEW)
.setObject(object)
.setActionStatus(Action.STATUS_TYPE_COMPLETED)
.build();
}
#Override
public void onStart() {
super.onStart();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client.connect();
AppIndex.AppIndexApi.start(client, getIndexApiAction());
}
#Override
public void onStop() {
super.onStop();
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
AppIndex.AppIndexApi.end(client, getIndexApiAction());
client.disconnect();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap mImageBitmap = (Bitmap) extras.get("data");
}
}
#Override
protected void onDestroy() {
super.onDestroy();
}
}
Here my adapter TaskAdapter :
package com.example.davidsimon.appexploit.classes;
import android.content.Context;
import android.graphics.Movie;
import android.support.v7.widget.ListViewCompat;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;
import com.example.davidsimon.appexploit.R;
import com.example.davidsimon.appexploit.activities.TasksActivity;
import java.util.ArrayList;
import java.util.List;
import static android.R.attr.data;
import static android.R.attr.value;
import static com.example.davidsimon.appexploit.R.id.checkBox;
/**
* Created by David SIMON on 22/08/2016.
*/
public class TaskAdapter extends RecyclerView.Adapter<TaskAdapter.MyViewHolder> {
private List<Task> TaskList;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public CheckBox checkBox;
public EditText finalComment;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.title);
checkBox = (CheckBox) view.findViewById(R.id.checkBox);
finalComment = (EditText) view.findViewById(R.id.FinalComment);
TextWatcher textWatcher = new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
int position = (int) finalComment.getTag();
TaskList.get(position).setComment(charSequence.toString());
}
#Override
public void afterTextChanged(Editable editable) {
}
};
finalComment.addTextChangedListener(textWatcher);
}
}
public TaskAdapter(List<Task> TaskList) {
this.TaskList = TaskList;
}
#Override
public TaskAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recyvlerview, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Task task = TaskList.get(position);
holder.title.setText(task.getTitle());
holder.finalComment.setTag(position);
holder.checkBox.setOnCheckedChangeListener(null);
holder.checkBox.setChecked(task.isState());
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
task.setState(b);
}
});
}
public Task getItem(int position){
return TaskList.get(position);
}
#Override
public int getItemCount() {
return TaskList.size();
}
}
And my Task.java
package com.example.davidsimon.appexploit.classes;
/**
* Created by David SIMON on 05/08/2016.
*/
public class Task {
String title;
boolean state;
String comment;
int period;
String type;
public Task(String title, boolean state, String comment, String type, int period) {
this.title = title;
this.state = state;
this.comment = comment;
this.type = type;
this.period = period;
}
#Override
public String toString() {
return "Title : "+ title +
"\nState : " + state +
"\nComment : " + comment +
"\nPeriod : " + period +
"\nType : " + type;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public void setState(boolean state) {
this.state = state;
}
public boolean isState() {
return state;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getPeriod() { return period; }
public void setPeriod(int period) { this.period = period; }
}
I just want to save data in my EditText "finalcomment". I already search some similar problem but I think my level is too low.
Thanks in advance
A RecyclerView will reuse your views. So whenever you scroll onBindViewHolder will be called. Within that method you need to setup the view with the correct data. You need to set the EditText in your onBindViewHolder which will likely require you to save the tex that has been entered. Here's an example of how you'd do that without the save logic:
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Task task = TaskList.get(position);
holder.title.setText(task.getTitle());
holder.finalComment.setTag(position);
// You need to save the entered text and then set it in onBindViewHolder
holder.finalComment.setText(THE TEXT FOR THE EDIT TEXT);
holder.checkBox.setOnCheckedChangeListener(null);
holder.checkBox.setChecked(task.isState());
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
task.setState(b);
}
});
}
I think you have a problem in recycling views.
Your RecyclerView reuse views that exited from the screen for other object, to save time and memory.
So what you need is to always set all desired data into onBindViewHolder method. Otherwise if a view exit from the visible screen and it is reused, it will be reused with old data.
Using EditText into RecyclerView is not a good decision, because you are mixing user inputs with presentation data.
If you want to keep this approach, you must find a way to save data associated to each RecyclerView item, to be then always able to set them to the right recycled view when it becomes again visible.
Obviously you need also to keep information of empty views.
Hope I have clarified enough
I seen a problem, if my solution doesn't work then let me know!
Inside your TaskAdapter class, onBindViewHolder() method:
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Task task = TaskList.get(position);
holder.title.setText(task.getTitle());
//this one is wrong
//holder.finalComment.setTag(position);
//while doing this you will get the text of final comment in your
//edit text of final comment
holder.finalComment.setText(task.getComment());
holder.checkBox.setOnCheckedChangeListener(null);
holder.checkBox.setChecked(task.isState());
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
task.setState(b);
}
});
}

Categories

Resources