I built a listview that displays dynamic buttons with the name of tables in a database. When a person clicks the button it's supposed to grab the text of the button and then pass that to the next activity which would populate the information corresponding to the database table and display that text at the top of the screen. The code I've written keeps crashing when I click the button. Is there something else I need to call or does this code not work with a button?
public class UserArea extends AppCompatActivity {
SectionListAdapter sectionListAdapter;
ListView listView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_user_area);
TextView tvWelcomeMsg = (TextView) findViewById(R.id.tvWelcome);
/**Get Sections and Display as buttons*/
listView = (ListView) findViewById(R.id.lvSections);
sectionListAdapter = new SectionListAdapter(this, R.layout.section_layout);
listView.setAdapter(sectionListAdapter);
Response.Listener<String> responseListener = new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonResponse = new JSONObject(response);
boolean success = jsonResponse.getBoolean("success");
/** If data successfully gathered*/
if (success) {
JSONArray jsonArray= jsonResponse.getJSONArray("Flights");
int count = 0;
String flight;
while(count<jsonArray.length()) {
JSONObject SL = jsonArray.getJSONObject(count);
flight = SL.getString("Flight");
SectionList sl = new SectionList(flight);
sectionListAdapter.add(sl);
count++;
}
}
/** If data is not gathered*/
else {
AlertDialog.Builder builder = new AlertDialog.Builder(UserArea.this);
builder.setMessage("Failed to connect")
.setNegativeButton("Retry", null)
.create()
.show();
}
}
/** if any other response is received*/
catch (JSONException e) {
e.printStackTrace();
}
}
};
/**Creates Request to get the data*/
GetSectionRequest getSections = new GetSectionRequest(responseListener);
/**Creates a queue to run the code*/
RequestQueue queue = Volley.newRequestQueue(UserArea.this);
queue.add(getSections);
/**End*/
/**Creates onclicklistener to pass clicked section name*/
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int i, long id) {
Intent intent = new Intent (UserArea.this, Personnel.class);
intent.putExtra("section", listView.getItemAtPosition(i).toString());
UserArea.this.startActivity(intent);
}
});
SectionListAdapter
public class SectionListAdapter extends ArrayAdapter {
List list = new ArrayList();
public SectionListAdapter(Context context, int resource) {
super(context, resource);
}
public void add(SectionList object) {
super.add(object);
list.add(object);
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row;
row = convertView;
SectionListAdapter.SectionListHolder sectionListHolder;
if (row == null){
LayoutInflater layoutInflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.section_layout, parent, false);
sectionListHolder = new SectionListAdapter.SectionListHolder();
sectionListHolder.bSection = row.findViewById(R.id.bSectionName);
}else{
sectionListHolder = (SectionListAdapter.SectionListHolder)row.getTag();
}
SectionList SectionList = (SectionList) this.getItem(position);
sectionListHolder.bSection.setText(SectionList.getFlight());
return row;
}
static class SectionListHolder{
Button bSection;
}
}
Log Cat
10-10 19:31:26.797 6595-6595/com.example.yikes.recall E/AndroidRuntime:
FATAL EXCEPTION: main
Process: com.example.yikes.recall, PID: 6595
java.lang.NullPointerException: Attempt to read from field 'android.widget.Button com.example.yikes.recall.SectionListAdapter$SectionListHolder.bSection' on a null object reference
I'm try code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final ListView listView = new ListView(this);
listView.setBackgroundColor(Color.WHITE);
setContentView(listView);
final String[] activities = new String[]{"Item1", "Item2", "Item3", "Item4"};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line);
listView.setAdapter(adapter);
for (String item : activities) {
adapter.add(item);
}
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String item = listView.getItemAtPosition(position).toString();
Intent intent = new Intent(MainActivity.this, SampleActivity.class);
intent.putExtra("item", item);
MainActivity.this.startActivity(intent);
}
});
}
It's working, I think
/**Creates Request to get the data*/
GetSectionRequest getSections = new GetSectionRequest(responseListener);
/**Creates a queue to run the code*/
RequestQueue queue = Volley.newRequestQueue(UserArea.this);
queue.add(getSections);
Need some time, you can add ProgressDialog when start app and dismiss when response callback. Hope it can help you!
Related
I get data in JSON from API, and there are id and url. Now, i need to create a button "Add to favorites" for each image that i display. When i try to set adapter.setListener(this);, i get an error, because i can't use string format.
How can i resolve this problem? I spend 5 hours on this, and can't resolve it :(
MainActivity:
protected void onCreate(Bundle savedInstanceState) {
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = findViewById(R.id.listItem);
favorites = findViewById(R.id.buttonFav);
catDetailsArrayList = new ArrayList<>();
myAdapter = new MyAdapter(MainActivity.this ,catDetailsArrayList);
searchbtn = findViewById(R.id.buttonSearch);
searchbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
catDetailsArrayList.clear();
myAdapter.notifyDataSetChanged();
displayCats();
}
});
});
}
private void displayCats() {
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try{
JSONArray jsonArray = new JSONArray(response);
for(int i=0; i<jsonArray.length(); i++){
JSONObject jsonObject1 = jsonArray.getJSONObject(i);
String jsonCatUrl2 = jsonObject1.getString("url");
String jsonCatId2 = jsonObject1.getString("id");
CatDetails catDetails = new CatDetails();
catDetails.setUrl(jsonCatUrl2);
catDetails.setId(jsonCatId2);
catDetailsArrayList.add(catDetails);
}
listView.setAdapter(myAdapter);
myAdapter.notifyDataSetChanged();
} catch(JSONException e){
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(),error.getMessage(),Toast.LENGTH_LONG).show();
}
});
requestQueue.add(stringRequest);
}
MyAdapter:
public class MyAdapter extends BaseAdapter {
public Activity activity;
public ArrayList<CatDetails> catDetailsArrayList;
public LayoutInflater inflater;
Button btn;
TextView idnr;
public MyAdapter(Activity activity, ArrayList<CatDetails> catDetailsArrayList) {
this.activity = activity;
this.catDetailsArrayList = catDetailsArrayList;
}
#Override
public Object getItem(int position) {
return catDetailsArrayList.get(position);
}
#Override
public long getItemId(int position) {
return (long)position;
}
#Override
public View getView(int position, View convertView, ViewGroup viewGroup) {
if (inflater == null) {
inflater = this.activity.getLayoutInflater();
}
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_item, null);
}
ImageView imageView = convertView.findViewById(R.id.ImageView);
final CatDetails catDetails = this.catDetailsArrayList.get(position);
Picasso.get().load(catDetails.getUrl()).into(imageView);
idnr =convertView.findViewById(R.id.textView);
btn = convertView.findViewById(R.id.buttonFav);
final String id = catDetails.getId();
idnr.setText(catDetails.getId());
return convertView;
}
#Override
public int getCount() {
return this.catDetailsArrayList.size();
}
I display the id that i receive from server for each item, it's ok, but i don't know how to set the button "add to favorites" to works fine. It must receive item id (that i received from server) as a param, but id is in string format.
final String id = catDetails.getId();
change it to
final String id = Integer.toString(catDetails.getId());
There are 2 autocomplete textview one for the city and one for the state. I want that when a user enters the state in autocomplete textview then based on state selection, city autocomplete text view should be automatically filled. Like the ecommerce app whenever someone enters the postal code in the address section then the city and state get automatically filled and also the user has the option to select.
MainActivity.java
public class MainActivity extends AppCompatActivity {
EditText edtxt_name_address, edtxt_email_address, edtxt_mobile_address, edtxt_alt_mob_address, edtxt_pincode, edtxt_addline1, edtxt_addline2;
Button buttonSaveAddress;
AutoCompleteTextView edtxt_city, edtxt_state;
private static final String KEY_STATE = "state";
private static final String KEY_CITIES = "cities";
private ProgressDialog pDialog;
private String cities_url = "http://api.androiddeft.com/cities/cities_array.json";
final List<State> statesList = new ArrayList<>();
final List<String> states = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edtxt_city = findViewById(R.id.edtxt_city);
edtxt_state = findViewById(R.id.edtxt_state);
loadStateCityDetails();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.select_dialog_item, states);
edtxt_state.setThreshold(1);//will start working from first character
edtxt_state.setAdapter(adapter);//setting the adapter data into the AutoCompleteTextView
//edtxt_city.setTextColor(Color.BLACK)
edtxt_state.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
buttonSaveAddress = findViewById(R.id.buttonSaveAddress);
buttonSaveAddress.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
saveAddress();
}
});
}
private void loadStateCityDetails() {
JsonArrayRequest jsArrayRequest = new JsonArrayRequest
(Request.Method.GET, cities_url, null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray responseArray) {
try {
//Parse the JSON response array by iterating over it
for (int i = 0; i < responseArray.length(); i++) {
JSONObject response = responseArray.getJSONObject(i);
String state = response.getString(KEY_STATE);
JSONArray cities = response.getJSONArray(KEY_CITIES);
List<String> citiesList = new ArrayList<>();
for (int j = 0; j < cities.length(); j++) {
citiesList.add(cities.getString(j));
}
statesList.add(new State(state, citiesList));
states.add(state);
Log.d("lskd", String.valueOf(statesList));
Log.d("lskd", String.valueOf(states));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//pDialog.dismiss();
//Display error message whenever an error occurs
Toast.makeText(getApplicationContext(),
error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
// Access the RequestQueue through your singleton class.
MySingleton.getInstance(this).addToRequestQueue(jsArrayRequest);
}
private void saveAddress() {
if (TextUtils.isEmpty(city)) {
edtxt_city.setError("Please enter your City");
edtxt_city.requestFocus();
return;
}
if (TextUtils.isEmpty(state)) {
edtxt_state.setError("Please enter your State");
edtxt_state.requestFocus();
return;
}
Intent profile_next = new Intent(MainActivity.this, ProfileNextActivity.class);
startActivity(profile_next);
}
}
State.java
public class State {
private String stateName;
private List<String> cities;
public State(String stateName, List<String> cities) {
this.stateName = stateName;
this.cities = cities;
}
public String getStateName() {
return stateName;
}
public List<String> getCities() {
return cities;
}
}
State and city has one to many relation, I didn't particularly understand what you meant by automatically filled. If you want to populate the related cities of the selected state do the following.
Inside your edtxt_state.setOnItemSelectedListener
edtxt_state.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
statesList.get(position).getCities(); //get your cities from selected state
//set adapter or notify city list of your `edtxt_city` AutoCompleteTextView
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
try this...
edtxt_state.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
List<String> cityList = statesList.get(position).getCities();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.select_dialog_item, cityList);
edtxt_city.setThreshold(1);//will start working from first character
edtxt_city.setAdapter(adapter);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
set your adapter inside loadStateCityDetails(); after getting stateList
statesList.add(new State(state, citiesList));
states.add(state);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.select_dialog_item, states);
edtxt_state.setThreshold(1);//will start working from first character
edtxt_state.setAdapter(adapter);
EDIT
edtxt_state.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String selection = (String) parent.getItemAtPosition(position);
int pos = -1;
for (int i = 0; i < statesList.size(); i++) {
if (statesList.get(i).getStateName().equals(selection)) {
pos = i;
break;
}
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.select_dialog_item, statesList.get(pos).getCities());
edtxt_city.setThreshold(1);//will start working from first character
edtxt_city.setAdapter(adapter);//setting the adapter data into the AutoCompleteTextView
}
});
you must get stateList
set city adapter as above
I am following a tutorial about multiple choice listview in android.
When executing the app, the listview shows some items, not all of them. After clicking on the listview, it shows all items.
I want to know where is the reason of that issue.
This is the code for MainActivity class:
public class MainActivity extends AppCompatActivity {
Toolbar toolbar;
FloatingActionButton fab;
ListView list;
TextView txt_menu;
String dipilih;
private static final String TAG = MainActivity.class.getSimpleName();
Adapter adapter;
ProgressDialog pDialog;
List<Data> itemList = new ArrayList<Data>();
// Sesuaikan dengan IP Address PC/LAptop atau ip emulator bawaan android 10.0.2.2
private static String url = "https://.../test/menu.php";
public static final String TAG_NAMA = "nama";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
fab = (FloatingActionButton) findViewById(R.id.fab);
list = (ListView) findViewById(R.id.list_menu);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String checkbox = "";
for (Data hold : adapter.getAllData()) {
if (hold.isCheckbox()) {
checkbox += "\n" + hold.getMenu();
}
}
if (!checkbox.isEmpty()) {
dipilih = checkbox;
} else {
dipilih = "Anda Belum Memilih Menu.";
}
formSubmit(dipilih);
}
});
callVolley();
adapter = new Adapter(this, (ArrayList<Data>) itemList);
list.setAdapter(adapter);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
adapter.setCheckBox(position);
}
});
}
private void formSubmit(String hasil){
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
LayoutInflater inflater = getLayoutInflater();
View dialogView = inflater.inflate(R.layout.form_submit, null);
dialog.setView(dialogView);
dialog.setIcon(R.mipmap.ic_launcher);
dialog.setTitle("Menu Yang Dipilih");
dialog.setCancelable(true);
txt_menu = (TextView) dialogView.findViewById(R.id.txt_menu);
txt_menu.setText(hasil);
dialog.setNeutralButton("CLOSE", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
dialog.show();
}
private void callVolley(){
itemList.clear();
// menapilkan dialog loading
pDialog = new ProgressDialog(this);
pDialog.setMessage("Loading...");
showDialog();
// membuat request JSON
JsonArrayRequest jArr = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
hideDialog();
// Parsing json
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
Data item = new Data();
item.setMenu(obj.getString(TAG_NAMA));
// menambah item ke array
itemList.add(item);
} catch (JSONException e) {
e.printStackTrace();
}
}
// notifikasi adanya perubahan data pada adapter
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hideDialog();
}
});
// menambah request ke request queue
AppController.getInstance().addToRequestQueue(jArr);
}
private void showDialog() {
if (!pDialog.isShowing())
pDialog.show();
}
private void hideDialog() {
if (pDialog.isShowing())
pDialog.dismiss();
}
}
And this is the Adapter class:
public class Adapter extends BaseAdapter {
private Context activity;
private ArrayList<Data> data;
private static LayoutInflater inflater = null;
private View vi;
private ViewHolder viewHolder;
public Adapter(Context context, ArrayList<Data> items) {
this.activity = context;
this.data = items;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int i) {
return i;
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int position, View view, ViewGroup viewGroup) {
vi = view;
final int pos = position;
Data items = data.get(pos);
if(view == null) {
vi = inflater.inflate(R.layout.list_row, null);
viewHolder = new ViewHolder();
viewHolder.checkBox = (CheckBox) vi.findViewById(R.id.cb);
viewHolder.menu = (TextView) vi.findViewById(R.id.nama_menu);
vi.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) view.getTag();
viewHolder.menu.setText(items.getMenu());
}
if(items.isCheckbox()){
viewHolder.checkBox.setChecked(true);
} else {
viewHolder.checkBox.setChecked(false);
}
return vi;
}
public ArrayList<Data> getAllData(){
return data;
}
public void setCheckBox(int position){
Data items = data.get(position);
items.setCheckbox(!items.isCheckbox());
notifyDataSetChanged();
}
public class ViewHolder{
TextView menu;
CheckBox checkBox;
}
}
If you need other code parts to detect the problem, please let me know.
EDIT
First launch
After clicking on the listview
The problem is this bit of your code in your adapter's getView() callback:
if(view == null) {
...
}else {
...
viewHolder.menu.setText(items.getMenu());
}
What's happening here is that you're only caling setText() when the item view is recycled by the ListView. The reason everything shows up after you click a checkbox is that the ListView rebinds everything when you call notifyDataSetChanged().
You should call this method outside of the if/else statement so that it is executed every time.
if(view == null) {
...
}else {
...
}
viewHolder.menu.setText(items.getMenu());
I think the issue you are having is coming from the getView() method in your Adapter class.
Since you are using a ViewHolder to recycle objects you are first checking if the exist first before creating them if(view == null). But, you are only creating them and not assigning the TextView objects a String value. You only do that once the object has already been created. So, when you click on an item, you are calling notifyDataSetChanged causing the list to be updated. Then the values are set in the `TextView.
So try this instead: put the line viewHolder.menu.setText(items.getMenu()); outside the conditional statement:
#Override
public View getView(int position, View view, ViewGroup viewGroup) {
vi = view;
final int pos = position;
Data items = data.get(pos);
if(view == null) {
vi = inflater.inflate(R.layout.list_row, null);
viewHolder = new ViewHolder();
viewHolder.checkBox = (CheckBox) vi.findViewById(R.id.cb);
viewHolder.menu = (TextView) vi.findViewById(R.id.nama_menu);
vi.setTag(viewHolder);
}else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.menu.setText(items.getMenu());
if(items.isCheckbox()){
viewHolder.checkBox.setChecked(true);
} else {
viewHolder.checkBox.setChecked(false);
}
return vi;
}
try this once
adapter = new Adapter(this, (ArrayList) itemList);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
adapter.setCheckBox(position);
}
});
list.setAdapter(adapter);
}
set adapter at the end
I've a listview which shows values from web service. Its fine when it loads the listview. But when I click on any item to open a new fragment (which shows details of the item) and get back to the same listview, its items doubles everytime. For example, if I have (in original) 5 items in total. Then when I get back from the fragment, the total count will be 10, then 15 and so on. It means the app is adding all items again and again. I searched for the solution and did what were the general solution like adapter.notifyDataSetChanged() but its still gets duplicated. If anyone can show me the problem, I would be grateful.
public class CustomListAdapter extends ArrayAdapter<Model> {
private Context mContext;
int resource;
private ArrayList<Model> mListData = new ArrayList<Model>();
public CustomListAdapter(Context mContext, int resource, ArrayList<Model> mListData) {
super(mContext, resource, mListData);
this.resource = resource;
this.mContext = mContext;
this.mListData = mListData;
}
public void setListData(ArrayList<Model> mListData) {
this.mListData = mListData;
notifyDataSetChanged();
}
#Override
public int getCount() {
return super.getCount();
}
#Override
public View getView(final int position, View convertView, final ViewGroup parent) {
View v = convertView;
final ViewHolder holder;
if (v == null) {
holder = new ViewHolder();
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
v = inflater.inflate(resource, parent, false);
holder.custname = (TextView) v.findViewById(R.id.cust_name);
holder.date = (TextView) v.findViewById(R.id.date);
holder.staffname = (TextView) v.findViewById(R.id.staff_name);
holder.time = (TextView) v.findViewById(R.id.time);
holder.service = (TextView) v.findViewById(R.id.service);
holder.refid = (TextView) v.findViewById(R.id.refid);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
final Model item = mListData.get(position);
holder.custname.setText(item.getCustname());
holder.date.setText(item.getDate());
holder.staffname.setText(item.getStaffname());
holder.time.setText(item.getTime());
holder.service.setText(item.getService());
holder.refid.setText(item.getRefid());
return v;
}
class ViewHolder {
TextView custname, date, staffname, time, service, refid;
}
}
public class ListFrag extends Fragment{
private SwipeMenuListView listView;
private CustomListAdapter adapter;
private CShowProgress cShowProgress;
private SQLiteHandler db;
private String uid, bookingId;
private ArrayList<Model> arrayList = new ArrayList<>();
private static final String BOOKED_LIST = "http://192.168.220.13/android/showbookinglist";
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.listfrag, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
listView = (SwipeMenuListView)view.findViewById(R.id.list);
db = new SQLiteHandler(getActivity());
cShowProgress = CShowProgress.getInstance();
fetchDetails();
adapter = new CustomListAdapter(getActivity(), R.layout.listitem, arrayList);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String a = arrayList.get(i).getCustname();
String b = arrayList.get(i).getStaffname();
String c = arrayList.get(i).getService();
String d = arrayList.get(i).getDate();
String e = arrayList.get(i).getTime();
String f = arrayList.get(i).getRefid();
String g = arrayList.get(i).getEmail();
String h = arrayList.get(i).getServprice();
String j = arrayList.get(i).getSpeclprice();
String k = arrayList.get(i).getStatus();
db.addDetails(a, b, c, d, e, f, g, h, j, k);
DetailsView details = new DetailsView();
((Bookings)getActivity()).replaceFragment(details);
}
});
}
private void fetchDetails() {
cShowProgress.showProgress(getActivity());
StringRequest stringRequest = new StringRequest(Request.Method.POST, BOOKED_LIST,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
cShowProgress.hideProgress();
try {
JSONArray jsonArray = new JSONArray(response);
for(int i=0; i<jsonArray.length(); i++){
JSONObject obj = jsonArray.getJSONObject(i);
Model model = new Model();
model.setCustname(obj.getString("customername"));
model.setDate(obj.getString("staffdate"));
model.setStaffname(obj.getString("staffname")+"(Staff)");
model.setTime(obj.getString("stafftime"));
model.setService(obj.getString("servicename"));
model.setRefid(obj.getString("booking_referenceid"));
model.setEmail(obj.getString("customeremail"));
model.setServprice(obj.getString("serviceprice"));
model.setSpeclprice(obj.getString("specialprice"));
model.setStatus(obj.getString("status"));
model.setBookid(obj.getString("bookingid"));
arrayList.add(model);
}
adapter.notifyDataSetChanged();
} catch (JSONException e) {
// JSON error
e.printStackTrace();
Toast.makeText(getActivity(), "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getActivity(), "VolleyError" + error.toString(), Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("spaid", "145");
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
requestQueue.add(stringRequest);
}
}
try to change it as.. B'coz you are adding the elements in previously created list.. So you have to clear it.
private void fetchDetails() {
if(arrayList!=null )arrayList.clear(); // this line
cShowProgress.showProgress(getActivity());
The thing is that when you get back to the fragment it is recreated and onViewCreated is called again. From there you call again fetchDetails() and then your are adding the whole List for a second time to the adapter. So you can clear the list before fetchDetails() or just if you have to fetch them again.
change your try - catch block of onResponse method by below.
try {
JSONArray jsonArray = new JSONArray(response);
arrayList = new ArrayList<>();
for(int i=0; i<jsonArray.length(); i++)
{
JSONObject obj = jsonArray.getJSONObject(i);
Model model = new Model();
model.setCustname(obj.getString("customername"));
model.setDate(obj.getString("staffdate"));
model.setStaffname(obj.getString("staffname")+"(Staff)");
model.setTime(obj.getString("stafftime"));
model.setService(obj.getString("servicename"));
model.setRefid(obj.getString("booking_referenceid"));
model.setEmail(obj.getString("customeremail"));
model.setServprice(obj.getString("serviceprice"));
model.setSpeclprice(obj.getString("specialprice"));
model.setStatus(obj.getString("status"));
model.setBookid(obj.getString("bookingid"));
arrayList.add(model);
}
adapter.notifyDataSetChanged();
This is happening because you are not clearing the arrayList. Due to this every time that you construct the array and the adapter, you are adding the elements into an array that already has elements.
That why you have 5, then 10, then 15 and so on..
Clear the array before adding new elements
arrayList.clear();
Or program another strategy like:
Not populate the array every time you return to the fragment.
Check if he element existe before add it into the array.
The code below works fine. It populates a list with values from a JSON response and will open a new activity on selection of any of the items, as well as displaying the number of the item.
My question is how to have the selected item open an activity with the specific information from that item. Example: I select "Bob" from the List, I am taken to a new activity with the name of Bob, his email, and his phone. Or any other values that the JSON might have sent. If I select "George" it will do the same, but with the details for George.
I attempted unsuccessfully to do this on my own. Any help is appreciated.
Details.java code:
public class Details extends AppCompatActivity implements AdapterView.OnItemClickListener {
// Log tag
private static final String TAG = Details.class.getSimpleName();
private static String url = "removed";
private List<LoadUsers> detailList = new ArrayList<LoadUsers>();
private ListView listView;
private CustomListAdapter adapter;
private Button ShowDetailsButton;
private Button AddDetails;
private ProgressDialog pDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.details_view);
listView = (ListView) findViewById(R.id.lv);
adapter = new CustomListAdapter(this, detailList);
listView.setAdapter(adapter);
listView.setOnItemClickListener(this);
ShowDetailsButton = (Button) findViewById(R.id.show_details);
AddDetails = (Button) findViewById(R.id.add_details);
// Progress dialog
pDialog = new ProgressDialog(this);
pDialog.setCancelable(false);
pDialog.setMessage("Loading...");
// changing action bar color
// getActionBar().setBackgroundDrawable(
// new ColorDrawable(Color.parseColor("#1b1b1b")));
ShowDetailsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
detailList.clear();
// Showing progress dialog before making http request
showPDialog();
// Creating volley request obj
JsonArrayRequest detailsReq = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
hidePDialog();
// Parsing json
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
LoadUsers details = new LoadUsers();
details.setTitle(obj.getString("name"));
details.setThumbnailUrl(obj.getString("image"));
details.setEmail(obj.getString("email"));
details.setPhone(obj.getString("phone"));
// adding to array
detailList.add(details);
} catch (JSONException e) {
e.printStackTrace();
}
}
// notifying list adapter about data changes
// so that it renders the list view with updated data
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePDialog();
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(detailsReq);
}
});
AddDetails.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent i = new Intent(Details.this, MoreDetails.class);
startActivity(i);
}
});
}
private void showPDialog() {
if (!pDialog.isShowing())
pDialog.show();
}
private void hidePDialog() {
if (pDialog.isShowing())
pDialog.dismiss();
}
public void onDestroy() {
super.onDestroy();
hidePDialog();
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(this, "Item Clicked: " + position, Toast.LENGTH_SHORT).show();
Intent i = new Intent(Details.this, onDetailsSelect.class);
startActivity(i);
}
}
CustomListAdapter.java code:
public class CustomListAdapter extends BaseAdapter {
public Activity activity;
private LayoutInflater inflater;
private List<LoadUsers> usersItems;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public CustomListAdapter(Activity activity, List<LoadUsers> usersItems) {
this.activity = activity;
this.usersItems = usersItems;
}
#Override
public int getCount() {
return usersItems.size();
}
#Override
public Object getItem(int location) {
return usersItems.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.list_row, null);
if (imageLoader == null)
imageLoader = AppController.getInstance().getImageLoader();
NetworkImageView thumbNail = (NetworkImageView) convertView.findViewById(R.id.thumbnail);
TextView title = (TextView) convertView.findViewById(R.id.title);
TextView email = (TextView) convertView.findViewById(R.id.lvemail);
TextView phone = (TextView) convertView.findViewById(R.id.lvphone);
// getting user data for the row
LoadUsers m = usersItems.get(position);
// thumbnail image
thumbNail.setImageUrl(m.getThumbnailUrl(), imageLoader);
// title
title.setText(m.getTitle());
// email
email.setText("Email: " + String.valueOf(m.getEmail()));
// phone
phone.setText("Phone: " + String.valueOf(m.getPhone()));
return convertView;
}
}
New Activity that is being opened on selection of item:
onDetailsSelect.java:
public class onDetailsSelect extends AppCompatActivity {
Toolbar toolbar;
ActionBarDrawerToggle mActionBarDrawerToggle;
DrawerLayout drawerLayout;
private TextView title, email, phone;
private List<LoadUsers> usersItems;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_onuserselect);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
NetworkImageView thumbNail = (NetworkImageView) findViewById(R.id.thumbnail);
title = (TextView) findViewById(R.id.title);
email = (TextView) findViewById(R.id.lvemail);
phone = (TextView) findViewById(R.id.lvphone);
}
}
Modify your onItemClick like that:
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(this, "Item Clicked: " + position, Toast.LENGTH_SHORT).show();
TextView title = (TextView) view.findViewById(R.id.title);
String title_text = title.getText().toString();
TextView email = (TextView) view.findViewById(R.id.lvemail);
String email_text = email.getText().toString();
TextView phone = (TextView) view.findViewById(R.id.lvphone);
String phone_text = phone.getText().toString();
Intent i = new Intent(Details.this, onDetailsSelect.class);
i.putExtra("title_intent", title_text);
i.putExtra("email_intent", email_text);
i.putExtra("phone_intent", phone_text);
startActivity(i);
}
And retrieve the intent values in onDetailsSelect Activity, in onCreate:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detail);
Intent i = getIntent();
String title = i.getStringExtra("title_intent");
String email = i.getStringExtra("email_intent");
String phone = i.getStringExtra("phone_intent");
}
You can pass your ArrayList and item position on which you have clicked in the ListView, to the new activity like this --
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
String item_position = String.valueOf(position);
ArrayList<ListRowItem> full_listitem = listitem;
Intent intent = new Intent(context,SecondActivity.class);
Bundle extras = new Bundle();
extras.putString(CRRNT_ROW_NUMBER, item_position);
extras.putSerializable(LISTITEM, full_listitem);
intent.putExtras(extras);
startActivity(intent);
}
});
In your 2nd Activity, you have to receive these using the below code --
Intent intent = getIntent();
Bundle extras = intent.getExtras();
item_position = extras.getString(FirstActivity.CRRNT_ROW_NUMBER);
listitem = (ArrayList<ListRowItem>)extras.getSerializable(FirstActivity.LISTITEM);
position = Integer.parseInt(item_position);
currentlistitem = listitem.get(position);
String a = currentlistitem.getA();
String b = currentlistitem.getB();
For all these implementations, you have to implement Serializable interface in both your Activities and also in the LoadUsers (Getter/Setter) class.
Hope this helps!