notifydatasetchanged() on custom base adapter having JSONArray - android

I made a custom base adapter class in which I pass the context of activity and a JSONArray. I use this JSONArray data to set all the views. But the notifyDataSetChanged() on the adapter is not working. Do I have to pass a string array or arraylist of strings in the adapter for notifyDataSetChanged() to work? Will it not work if I pass JSONArray?
My Custom Adapter class code:
public class InboxMessagesAdapter extends BaseAdapter {
Activity act;
SharedPreferences prefs;
LayoutInflater Inflater;
JSONArray arrayOfMessages;
public InboxMessagesAdapter(Activity a, JSONArray arry) {
act = a;
arrayOfMessages = arry;
prefs = PreferenceManager.getDefaultSharedPreferences(a);
Inflater = (LayoutInflater) act
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return arrayOfMessages.length();
}
#Override
public Object getItem(int arg0) {
return arg0;
}
#Override
public long getItemId(int arg0) {
return arg0;
}
#Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
View v1 = arg1;
try {
final int x = arg0;
JSONObject js = arrayOfMessages.getJSONObject(arg0);
v1 = Inflater.inflate(R.layout.element_inbox, null);
TextView titleOfMessage = (TextView) v1
.findViewById(R.id.msg_inbox_title);
TextView timeOfMessage = (TextView) v1
.findViewById(R.id.msg_inbox_time);
final CheckBox selectMessage = (CheckBox) v1
.findViewById(R.id.msg_inbox_check_button);
ImageView attachment = (ImageView) v1
.findViewById(R.id.msg_inbox_attachment);
ImageView starStatus = (ImageView) v1
.findViewById(R.id.msg_inbox_addtofav);
if (js.getString("StarStatus").equals("0"))
starStatus.setImageResource(R.drawable.btn_add_to_fav_normal);
else
starStatus.setImageResource(R.drawable.btn_add_to_fav_pressed);
if (js.getString("AttachmentStatus").equals("0"))
attachment.setVisibility(View.GONE);
titleOfMessage.setText(js.getString("MessageSubject"));
String arr[] = js.getString("MessageDate").split(" ");
try {
timeOfMessage.setText(arr[1] + arr[2]);
} catch (Exception e) {
timeOfMessage.setText(js.getString("MessageDate"));
}
v1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
try {
Intent in = new Intent(act, MessageActivity.class);
in.putExtra("data", arrayOfMessages.getJSONObject(x)
.toString());
act.startActivity(in);
} catch (Exception e) {
e.printStackTrace();
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
return v1;
}
}

you must be updating a different object of arrayOfMessages create a function in adapter like:
public void setArrayOfMessages(JSONArray arrayOfMessages){
this.arrayOfMessages=arrayOfMessages;
}
and before calling notifyDataSetChanged all this:
adapter.setArrayOfMessages(object);
adapter.notifyDataSetChanged();

Better take your data from Json Array into an Arraylist or List and then apply notifyDataSetChanged.

Related

Android Getting Bound Object from OnClick

I'm totally stuck with something. I'm trying to do simple de-reference of a clicked object in Android environment but for the life of me can't find a way.
I have a MainView where I load json objects and I pass these objects to my adapter where I find these to a list. I have onClick on a TextView items in a list to capture click events.
Issue: the OnClick fires but I can't get back the original bound object from there, or I'm not sure how? I was trying to use a position variable that increments when getView function gets called for each row, but my position when OnClick happens always points to the last record in my list. I also tried implementing onItemClick in MainView but that never seems to fire.
How can I get back the object I bound to my TextView? Thank you in advance for any assistance with this.
public class MainActivity extends AppCompatActivity {
private static final String LOCATION_KEY = "location";
SharedPreferences pref;
SharedPreferences.Editor editor;
public JSONObject jsonObj = null;
ListView mainList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(com.digitour.www.R.layout.activity_main);
// Load state from shared preferences
pref= getApplicationContext().getSharedPreferences("MyPref", MODE_PRIVATE);
editor=pref.edit();`enter code here`
mainList = (ListView) findViewById(com.digitour.www.R.id.checkableList);
try {
jsonObj=new JSONObject(pref.getString("json",null));
// Bind Data and pass the json object read from a file to the adapter
MainViewAdapter customListViewAdapter = new MainViewAdapter(this, jsonObj);
mainList.setAdapter(customListViewAdapter);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is the adapters code:
public class MainViewAdapter extends BaseAdapter {
private LayoutInflater layoutInflater;
private Context context;
private JSONArray listItems;
private int positionPrivate;
private JSONObject jsonObj;
public MainViewAdapter(Context context, JSONObject jsonObj) {
layoutInflater = LayoutInflater.from(context);
this.context = context;
this.jsonObj = jsonObj;
JSONObject jObjectResult = null;
try {
jObjectResult = jsonObj.getJSONObject("Items");
this.listItems = jObjectResult.getJSONArray("Item");
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final SharedPreferences pref= context.getApplicationContext ().getSharedPreferences("MyPref", context.MODE_PRIVATE);
final SharedPreferences.Editor editor = pref.edit();
try {
positionPrivate = position;
if(convertView == null){
convertView = layoutInflater.inflate (com.digitour.www.R.layout.activity_row,parent,false);
}
TextView textView = (TextView) convertView.findViewById (com.digitour.www.R.id.rowText);
textView.setText(listItems.getJSONObject(position).getString ("description"));
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try{
//Trying to get here the bound object
TextView tv = (TextView)v;
int id = tv.getId();
if (listItems != null){
JSONObject clickedItem = listItems.getJSONObject(positionPrivate); // positionPrivate always indexed to last item in a list
Intent intent = new Intent(context, DetailActivity.class);
context.startActivity(intent);
}
} catch (Exception e){
e.printStackTrace();
}
}
});
return convertView;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
You have a single member variable private int positionPrivate that you store the index in. It can only hold one index, so ends up with the last index that was written to it.
Try removing this variable and just use the position parameter in your getView function.
JSONObject clickedItem = listItems.getJSONObject(position);
I think what you are looking for is a setTag(Object tag) method.
textView.setTag(position)
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = (int) textView.getTag()
if (listItems != null) {
JSONObject clickedItem = listItems.getJSONObject(position);
...
}
}
}

Please suggest me on proper usage of notifyDataSetChanged()

I'm using view pager with swiping tab layouts. And i'm displaying list view of data using custom adapter. And also onclick of list view i have a list view detail activity where I'm displaying data in more detail. In these detail activity i'm performing some changes to the data(some post method). after that I create an instance of customAdapter class and call notifyDataSetChanged() in order to refresh list view. My problem over here is the list view some times refreshes quickly and some times there is a delay of some seconds.
So, Can somebody suggest me proper usage of list view and what changes needs to be done in order to refresh list view whenever a post method is performed.
My code Fragment class:
private void showJsonData(String response) {
try {
String serviceID = LoggedInUserStore.getLoggedInServiceId(getContext());
List<Complaint> userList = new ArrayList<>(); //ArrayList of type user(POJO CLASS)
JSONArray jsonArray = new JSONArray(response);
for (int i = 0; i < jsonArray.length(); i++) {
if (serviceID.equals(jsonArray.getJSONObject(i).getString("ServiceID"))) {
if (jsonArray.getJSONObject(i).getString("CallStatusID").equalsIgnoreCase("1")) {
userList.add(0, Complaint.fromJson(jsonArray.getJSONObject(i))); //
}
}
}
assignAdapter = new AssignAdapter(getActivity(), userList);
listView.setAdapter(assignAdapter);
listView.invalidateViews();
assignAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
My custom adapter class
public class AssignAdapter extends BaseAdapter implements Filterable {
List<Complaint> ticket = new ArrayList<>();
private Context context;
String ticketNo, complaint, raiseDate;
Complaint user;
List<Complaint> temporaryList = new ArrayList<>();
/*String status, priority;*/
public AssignAdapter(Context context, List<Complaint> ticket) {
this.context = context;
this.ticket = ticket;
this.temporaryList = ticket;
}
#Override
public int getCount() {
return temporaryList.size();
}
#Override
public Object getItem(int position) {
return temporaryList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public class viewHolderItem {
TextView ticketNumberText, complaintNameText, raisedDateText;
}
//Set the layout for the fragment and return it.
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
viewHolderItem holder;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.custom_list_view, null, true);
holder = new viewHolderItem();
holder.ticketNumberText = (TextView) convertView.findViewById(R.id.ticketIdSupervisor);
holder.complaintNameText = (TextView) convertView.findViewById(R.id.complaintNameSupervisor);
convertView.setTag(holder);
} else {
holder = (viewHolderItem) convertView.getTag();
}
user = temporaryList.get(position);
if (user != null) {
//Get the Ticket Number
Typeface custom_font = Typeface.createFromAsset(context.getAssets(), "fonts/DroidSerif.ttf");
ticketNo = temporaryList.get(position).getTicketNumber();
holder.ticketNumberText.setText(ticketNo);
holder.ticketNumberText.setTag("ticketNumber");
holder.ticketNumberText.setTypeface(custom_font);
//Get the complaint Name
complaint = temporaryList.get(position).getComplaintDetails();
holder.complaintNameText.setText(complaint);
holder.complaintNameText.setTag("complaint");
holder.complaintNameText.setTypeface(custom_font);
}
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(context.getApplicationContext(), ComplaintDetailsSupervisor.class);
i.putExtra("COMPLAINT NAME", temporaryList.get(position).getComplaintDetails());
i.putExtra("RAISED DATE", temporaryList.get(position).getRaisedDate().substring(0, 10));
context.startActivity(i);
}
});
notifyDataSetChanged();
return convertView;
}
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
}
My List view detail activity class
dialogButtonOk.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
assignComplaint();
al.remove(position);
AssignAdapter assignAdapter = new AssignAdapter(getApplicationContext(), al);
assignAdapter.notifyDataSetChanged();
ComplaintDetailsSupervisor.this.finish();
} catch (JSONException e) {
e.printStackTrace();
}
}
});
dialogButtonNo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
}
}
});
}
public void assignComplaint() throws JSONException {
//my custom method...
}
In the list view detail activity class i'm doing this
al.remove(position);
AssignAdapter assignAdapter = new AssignAdapter(getApplicationContext(), al);
assignAdapter.notifyDataSetChanged();
ComplaintDetailsSupervisor.this.finish();
Removing the position of list view and immediately calling adapter. This works fine but I don't know why sometimes it does not refreshes..May be when list view has a single item it does not refreshes immediately.
You are creating a new adapter and calling notifyDatasetChanged on it but have not called setAdapter with the new adapter as a parameter, hence why your list ist not refreshed.
You need to call
setAdapter(assignAdapter)
or reuse your existing assignAdapter and then call notifyDatasetChanged() on it.

setting onClickListener on listView that is populated with json

i have implemented a multi colum list view that is populated from json data. i also have set an onClickListener to it. but on running the app when i click the listView i am only able to fetch the first item of the list.
what i want to acheive is when i click on any item in the listView i should be able to get the row item. the code that i used is as follows
Adapter.java
private Activity activity;
private static ArrayList prefrenceid,partnerid;
private static LayoutInflater inflater = null;
public CompanyRegistrationAdapter(Activity a, ArrayList pref, ArrayList part) {
activity = a;
this.prefrenceid = pref;
this.partnerid=part;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return prefrenceid.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
if (convertView == null)
vi = inflater.inflate(R.layout.company_registation_adapter, null);
TextView preferences = (TextView) vi.findViewById(R.id.textView20);
String song = prefrenceid.get(position).toString();
preferences.setText(song);
TextView partner = (TextView) vi.findViewById(R.id.textView21);
String song2 = partnerid.get(position).toString();
partner.setText(song2);
return vi;
}
MainActivity.java
AsyncHttpClient usercheck = new AsyncHttpClient();
usercheck.get("REST URL", new AsyncHttpResponseHandler() {
public void onSuccess(String response) {
try {
progressDialog.hide();
JSONObject obj3 = new JSONObject(response);
final JSONArray jsonArray3 = obj3.getJSONArray("REST Method");
int length3 = jsonArray3.length();
if (length3 != 0) {
for (int i = 0; i < length3; i++) {
JSONObject user3 = jsonArray3.getJSONObject(i);
preference_array.add(user3.getString("GCP_NUMBER").toString());
partner_array.add(user3.getString("COMPANY_NAME").toString());
}
adapter = new CompanyRegistrationAdapter(CompanyRegistrationResult.this, preference_array, partner_array);
fav.setAdapter(adapter);
fav.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
try {
String iPartnerID = jsonArray3.getJSONObject(position).getString("ID");
Toast.makeText(getApplicationContext(),iPartnerID,Toast.LENGTH_SHORT).show();
Intent compRegister=new Intent(getApplicationContext(),CompanyRegistration.class);
compRegister.putExtra("gcp", gcp);
compRegister.putExtra("compName", compName);
startActivity(compRegister);
} catch (JSONException e) {
e.printStackTrace();
}
String gcp=((TextView) findViewById(R.id.textView20)).getText().toString();
String compName=((TextView) findViewById(R.id.textView21)).getText().toString();
}
});
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

getActivity() method return null

I wrote this code but getActivity method return null out onCreateView method.
public class HomeScreen extends Fragment {
private Context context;
ViewPager viewPager;
GridView listGrid;
Bitmap[] bitmaps ;
LinearLayout indicator;
Button first,second;
String[] path ;
TextView imageTitle;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.home_screen, container, false);
listGrid = (GridView) v.findViewById(R.id.grid_view);
viewPager = (ViewPager)v.findViewById(R.id.view_pager);
indicator = (LinearLayout)v.findViewById(R.id.indicator);
first = (Button) v.findViewById(R.id.bfirst);
second = (Button) v.findViewById(R.id.bsecond);
imageTitle = (TextView) v.findViewById(R.id.myImageTitle);
Typeface tf = Typeface.createFromAsset(HomeScreen.this.getActivity().getAssets(), "fonts/Medium.otf");
imageTitle.setTypeface(tf);
new GetCategories().execute();
return v;
}
class GetCategories extends AsyncTask {
#Override
protected Object doInBackground(Object[] params) {
JSONArray dataJsonArr = null;
JsonParser jParser = new JsonParser();
// get json string from url
JSONObject json = jParser.getJSONFromUrl("http://192.168.88.12/index.php");
try{
// get the array of users
dataJsonArr = json.getJSONArray("Users");
//Arrays of data
bitmaps = new Bitmap[dataJsonArr.length()];
path = new String[dataJsonArr.length()];
for (int i = 0; i < dataJsonArr.length(); i++) {
JSONObject c = dataJsonArr.getJSONObject(i);
InputStream in = new URL(c.getString("image")).openStream();
bitmaps[i] = BitmapFactory.decodeStream(in);
path[i] = c.getString("title");
}
}catch (JSONException e){
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Object o) {
ListAdapter adapter=new ListAdapter(HomeScreen.this.getActivity(), path,bitmaps);
listGrid.setAdapter(adapter);
ImageAdapter sliderAdapter = new ImageAdapter(HomeScreen.this.getActivity(),bitmaps,indicator,first,second,imageTitle,path);
viewPager.setAdapter(sliderAdapter);
}
}
public void onItemClick(int mPosition){
Log.i("Log:", " on item click : " + context);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
context = activity;
}
}
public class ListAdapter extends ArrayAdapter {
private final Activity context;
private final String[] title;
private final Bitmap[] image;
public ListAdapter(Activity context, String[] title, Bitmap[] image) {
super(context, R.layout.list_row, title);
this.context=context;
this.title=title;
this.image=image;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater=context.getLayoutInflater();
View rowView=inflater.inflate(R.layout.list_row, null, true);
TextView txtTitle = (TextView) rowView.findViewById(R.id.text);
ImageView imageView = (ImageView) rowView.findViewById(R.id.image);
txtTitle.setTypeface(Typeface.createFromAsset(ListAdapter.this.getContext().getAssets(), "fonts/Light.otf"));
txtTitle.setText(title[position]);
imageView.setImageBitmap(image[position]);
rowView.setOnClickListener(new OnItemClickListener(position));
return rowView;
}
/********* Called when Item click in ListView ************/
private class OnItemClickListener implements View.OnClickListener {
private int mPosition;
OnItemClickListener(int position){
mPosition = position;
}
#Override
public void onClick(View v) {
HomeScreen homeScreen = new HomeScreen();
homeScreen.onItemClick(mPosition);
}
}
}
This is done because your Fragment is not attached to any activity so far.
getActivity returns null before the onAttach(Activity) returs and after the onDetach() better check out Fragment Documentation to see the proper usage of fragments.
Also, stop using such references to context
ListAdapter.this.getContext() or HomeScreen.this.getActivity() they are prune to crashes and far from android logic.
To avoid these issues consider using Loader instead of AsyncTask here is a good tutorial how loaders work implement: https://stackoverflow.com/a/20991394/944070
You are not using a FragmentTransaction to interact with your Fragment. This means that the FragmentManager is not able to play a role when it comes to the Fragment lifecycle, hence your Activity is null because the Fragment is never attached to the Activity.

OnItemClickListener getting data from model

I am fairly new to Android development and I am trying to build a ListView which get data from web service using gson. I have a model class, a list class, an adapter class and the activity class.
The list works fine and it got the data, and now I want to integrate the OnItemClickListener to it and pass the data to the 2nd activity. And I'd like to get the item id (DistrictId) and pass it to the next Activity(listView) instead of the row id. It would be great if someone could show me the light... as the documentation is not as clear to understand and because I am new.
Below is my code.
The model class
package com.sample.myapp;
public class DistrictModel {
private String id;
private String districtName;
public String getDistrictId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDistrictName(){
return districtName;
}
public void setDistrictEN(String districtName){
this.districtName = districtName;
}
}
The List class
public class DistrictList {
private List<DistrictModel> districts;
public List<DistrictModel> getDistricts(){
return districts;
}
public void setDistrictList(List<DistrictModel> districts){
this.districts = districts;
}
}
The Adapter class
public class DistrictAdapter extends ArrayAdapter<DistrictModel>{
int resource;
String response;
Context context;
private LayoutInflater dInflater;
public DistrictAdapter(Context context, int resource, List<DistrictModel> objects) {
super(context, resource, objects);
this.resource = resource;
dInflater = LayoutInflater.from(context);
}
static class ViewHolder {
TextView title;
}
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
//Get the current location object
DistrictModel lm = (DistrictModel) getItem(position);
//Inflate the view
if(convertView==null)
{
convertView = dInflater.inflate(R.layout.item_district, null);
holder = new ViewHolder();
holder.title = (TextView) convertView
.findViewById(R.id.district_name);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.title.setText(lm.getDistrictName());
return convertView;
}
}
The activity class
public class DistrictListActivity extends Activity{
LocationManager lm;
ArrayList<DistrictModel> districtArray = null;
DistrictAdapter districtAdapter;
DistrictList list;
ListView lv;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.districtlist_layout);
lv = (ListView) findViewById(R.id.list_district);
districtArray = new ArrayList<DistrictModel>();
districtAdapter = new DistrictAdapter(DistrictListActivity.this, R.layout.item_district, districtArray);
lv.setTextFilterEnabled(true);
lv.setAdapter(districtAdapter);
try {
new DistrictSync().execute("http://aws.something.com/service");
} catch(Exception e) {}
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View convertView, int position, long id) {
AlertDialog.Builder adb=new AlertDialog.Builder(DistrictListActivity.this);
adb.setTitle("LVSelectedItemExample");
adb.setMessage("Selected Item is = "+(lv.getItemIdAtPosition(position)));
adb.setPositiveButton("Ok", null);
adb.show();
}
}); **//i'd like to get the DistrictId from the json data.**
}
private class DistrictSync extends AsyncTask<String, Integer, DistrictList> {
protected DistrictList doInBackground(String... urls) {
DistrictList list = null;
int count = urls.length;
for (int i = 0; i < count; i++) {
try {
// ntar diganti service
RestClient client = new RestClient(urls[i]);
try {
client.Execute(RequestMethod.GET);
} catch (Exception e) {
e.printStackTrace();
}
String json = client.getResponse();
list = new Gson().fromJson(json, DistrictList.class);
//
} catch(Exception e) {}
}
return list;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(DistrictList dislist) {
for(DistrictModel lm : dislist.getDistricts())
{
districtArray.add(lm);
}
districtAdapter.notifyDataSetChanged();
}
}
}
For testing purpose, now I click the row it will show me the row id, so I know the onclick listener works, but I just want it to grab me the DistrictId so I can use it to pass to the next activity.
Thank you so much.
(out of my head) Try this:
((DistrictModel)lv.getAdapter().getItem(position)).getDistrictId();
Generally when you want to pass data from one Activity to another, you just place it into the Intent that you use to create the new Activity.
For example (and here are some additional examples):
Intent i = new Intent(context, MyNewActivity.class);
i.putExtra("MyCurrentHealth", mCurrentHealth);
context.startActivity(i);
To retrieve the data do this:
Bundle extras = getIntent().getExtras();
if (extra != null) {
... // Do stuff with extras
}

Categories

Resources