Unlimited scrolling with JSON Adapter & ListView - android

I'm using ListView that retrieves data from external URL with JSON.
When I run my app, it shows only maximum of 10 results since my api query returns maximum of 10 results PER page.
What i'm trying to do is, that when the user scrolls down to the end of this 10 results, it will load more results (one by one would be even greater) from my JSON external URL (API).
This is how I'm using my ListView & JSONAdapter:
TabFragment1.java
ListView mainListView = (ListView) v.findViewById(R.id.main_listview);
mJSONAdapter = new JSONAdapter(getActivity(), inflater);
mainListView.setAdapter(mJSONAdapter);
getUpdates();
getUpdates()
private void queryUpdates(double lat, double lon, int distance) {
// Create a client to perform networking
AsyncHttpClient client = new AsyncHttpClient();
// Show ProgressBar to inform user that a task in the background is occurring
mProgress.setVisibility(View.VISIBLE);
// Have the client get a JSONArray of data
// and define how to respond
client.get(API_URL + "?lat=" + lat + "&lon=" + lon + "&distance=" + distance,
new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONObject jsonObject) {
// 11. Dismiss the ProgressDialog
mProgress.setVisibility(View.GONE);
// update the data in your custom method.
mJSONAdapter.updateData(jsonObject.optJSONArray("docs"));
}
#Override
public void onFailure(int statusCode, Throwable throwable, JSONObject error) {
// 11. Dismiss the ProgressDialog
mProgress.setVisibility(View.GONE);
getActivity().setContentView(R.layout.bad_connection);
}
});
}
My JSONAdapter.java
public class JSONAdapter extends BaseAdapter implements StickyListHeadersAdapter {
Context mContext;
LayoutInflater mInflater;
JSONArray mJsonArray;
public JSONAdapter(Context context, LayoutInflater inflater) {
mContext = context;
mInflater = inflater;
mJsonArray = new JSONArray();
}
#Override
public int getCount() {
return mJsonArray.length();
}
#Override
public Object getItem(int position) {
return mJsonArray.optJSONObject(position);
}
#Override
public long getItemId(int position) {
// your particular dataset uses String IDs
// but you have to put something in this method
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
// check if the view already exists
// if so, no need to inflate and findViewById again!
if (convertView == null) {
// Inflate the custom row layout from your XML.
convertView = mInflater.inflate(R.layout.row_place_update, null);
// create a new "Holder" with subviews
holder = new ViewHolder();
holder.myImageView = (ImageView) convertView.findViewById(R.id.myImage);
holder.myTextView = (TextView) convertView.findViewById(R.id.myText);
// hang onto this holder for future recyclage
convertView.setTag(holder);
} else {
// skip all the expensive inflation/findViewById
// and just get the holder you already made
holder = (ViewHolder) convertView.getTag();
}
// More code after this
// Get the current book's data in JSON form
JSONObject jsonObject = (JSONObject) getItem(position);
// Grab the title and author from the JSON
if (jsonObject != null) {
//Get from JSON
String myImage = jsonObject.optString("myImage");
String myText = jsonObject.optString("myText");
//Replace Them
Picasso.with(mContext).load(myImage).placeholder(R.drawable.loading).into(holder.myImageView);
holder.myTextView.setText(myText);
}
return convertView;
}
// this is used so you only ever have to do
// inflation and finding by ID once ever per View
private static class ViewHolder {
public ImageView myImageView;
public TextView myTextView;
}
public void updateData(JSONArray jsonArray) {
// update the adapter's dataset
mJsonArray = jsonArray;
notifyDataSetChanged();
}
}
how I can show more results by adding &page=2, &page=3 to the API_URL and load these results in my ListVIew, in addition to the old results?

Related

App get crashed when trying to display Data through listview

I'm trying to get data using retrofit2 and display those data using a list passing through as a parameter of Custom adapter. When I store data in a List in onResponse() method, in onResponse() method list have some value. But in oncreate() method its give me null. Though, I declared List as global. When I run the app sometimes its display nothing and sometimes app get crash. I know it's sounds like crazy. But it's happen. so, I want to know, what's wrong with my Code? how can I display data in listview?
Forgive me if something wrong with my question pattern yet this my maiden question at this site.
MainActivity`
public class LaboratoryValues extends AppCompatActivity {
public List<Data> productList = null;
List<Data>arrayList = null;
int size;
String st;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_laboratory_values);
//productList = new ArrayList<Data>();
getInvestigation();
for(int i =0; i < size; i++){
st = arrayList.get(i).getName();
}
System.out.println("Name : "+st);//here print Name : null
ListView lview = (ListView) findViewById(R.id.listview);
ListviewAdapter adapter = new ListviewAdapter(this, arrayList);
lview.setAdapter(adapter);
}
private void getInvestigation() {
/* final ProgressDialog progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setCancelable(false); // set cancelable to false
progressDialog.setMessage("Please Wait"); // set body
progressDialog.show(); // show progress dialog*/
ApiInterface apiService =
Api.getClient(ApiInterface.BASE_URL).create(ApiInterface.class);
Call<Investigation> investigationCall = apiService.getInvestigation();
investigationCall.enqueue(new Callback<Investigation>() {
#Override
public void onResponse(Call<Investigation> call, Response<Investigation> response) {
arrayList = response.body().getData();
//productList.addAll(arrayList);
size = response.body().getData().size();
for (int i = 0; i < size; i++) {
System.out.println("Name : " + arrayList.get(i).getName());//here printing Name is ok
}
}
#Override
public void onFailure(Call<Investigation> call, Throwable t) {
Toast.makeText(getApplicationContext(),"data list is empty",Toast.LENGTH_LONG).show();
}
});
}
}
Custom Adapter (listviewAdapter)
public class ListviewAdapter extends BaseAdapter {
public List<Data> productList;
Activity activity;
//Context mContext;
public ListviewAdapter(Activity activity, List<Data> productList) {
super();
this.activity = activity;
this.productList = productList;
}
#Override
public int getCount() {
return productList.size();
}
#Override
public Object getItem(int position) {
return productList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
private class ViewHolder {
TextView name;
TextView normal_finding;
TextView increased;
TextView decreased;
TextView others;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
LayoutInflater inflater = activity.getLayoutInflater();
if (convertView == null) {
convertView = inflater.inflate(R.layout.listview_row, null);
holder = new ViewHolder();
holder.name = convertView.findViewById(R.id.name);
holder.normal_finding =convertView.findViewById(R.id.normal_finding);
holder.increased = convertView.findViewById(R.id.increased);
holder.decreased = convertView.findViewById(R.id.decreased);
holder.others =convertView.findViewById(R.id.others);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Data item = productList.get(position) ;
holder.name.setText(item.getName());
System.out.println("holderName : "+item.getName() );
holder.normal_finding.setText(item.getNormal_finding());
System.out.println("holderName : "+item.getNormal_finding() );
holder.increased.setText(item.getIncreased());
holder.decreased.setText(item.getDecreased());
holder.others.setText(item.getOthers());
return convertView;
}
}
It's perfectly normal that it dosent work.
putting your method getInvistigation() before the loop does not mean that the response of your request was done
Calling a webservice creates another thread that waits for the server to send the response, sometimes the response takes time depends from the server and the latency of your internet connection.
you simply need to place the treatment (the loop and adapter) inside getInvistagion after getting the data.

Listview with complex item having a microsecond delay when loading

I've spent two days trying to find a solution for this problem and couldn't find it anywhere. My problem is: I have a List View in which each item has 4 text views and an ImageView. I'm fetching data from a website using Volley. The data loads normally and when a I scroll down everything works perfectly. The problem is when I scroll back. When I'm scrolling back the images and textviews have a 0.5 delay to appear (First I see the picture of the last item) and then the content is shown. I've already tried recyclerview and listview with viewholder. This "flick" persists in both solutions.
public class BigCategoryListViewAdapter extends BaseAdapter{
private Context context;
private String[] smallCatsList;
private News news;
private ImageLoader imageLoader;
static class myViewHolder{
TextView smallCatName;
RelativeLayout spinner;
ImageView newsImageView;
TextView newsTitle;
TextView newsContent;
}
public BigCategoryListViewAdapter(Context context, String[] smallCatsList){
this.context = context;
this.smallCatsList = smallCatsList;
this.imageLoader = ImageLoader.getInstance();
if(!this.imageLoader.isInited()) { this.imageLoader.init(ImageLoaderConfiguration.createDefault(context));}
}
#Override
public int getCount() {
return smallCatsList.length;
}
#Override
public Object getItem(int position) {
return smallCatsList[position];
}
#Override
public long getItemId(int position) {return 0;} //modificar aqui
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final myViewHolder mvh;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.bigcat_listview,null);
mvh = new myViewHolder();
mvh.smallCatName = (TextView) convertView.findViewById(R.id.bigcat_viewpager_smallcat);
mvh.spinner = (RelativeLayout) convertView.findViewById(R.id.spinner);
mvh.newsImageView = (ImageView) convertView.findViewById(R.id.bigcat_viewpager_imageView);
mvh.newsTitle = (TextView) convertView.findViewById(R.id.bigcat_viewpager_news_title);
mvh.newsContent = (TextView) convertView.findViewById(R.id.bigcat_viewpager_content);
convertView.setTag(mvh);
mvh.smallCatName.setText(smallCatsList[position]);
JSONObject params = new JSONObject();
try{
params.put("slug",smallCatsList[position]);
params.put("startIndex", 0);
params.put("endIndex", 0);
}catch (Exception e) {
Log.e(getClass().toString(), "Error setting params for communication with server");
e.printStackTrace();
}
Volley volley = Volley.getVolley(context);
volley.runRequest(Request.Method.POST, VolleyConstants.PROD_URL + VolleyConstants.NEWS_FETCH_ROUTE,
params, new Response.Listener<JSONObject>() {
//---------------------Volley------------------//
#Override
public void onResponse(JSONObject response) {
JSONArray responseArr = null;
try {
responseArr = response.getJSONArray("newsArr");
} catch (Exception e) {
e.printStackTrace();
}
for (int i = 0; i < responseArr.length(); i++) {
try {
JSONObject object = responseArr.getJSONObject(i);
String photoURLString = object.getString("photo");
String titleString = object.getString("title");
String publisherString = object.getString("publisher");
String dateString = object.getJSONObject("date").getString("date");
String contentString = object.getString("contents");
String urlString = object.getString("url");
news = new News(photoURLString, titleString, publisherString, dateString, contentString,urlString);
} catch (Exception e) {
news = new News("Unknown", "Unknown", "Unknown", "Unknown", "Unknown","Unknown");
}
}
//tv2.setText(news.getNewsDate());
mvh.newsContent.setText(news.getNewsContent());
mvh.newsTitle.setText(news.getNewsHead());
//---------------------Image Loading------------------//
try {
URL url = new URL(news.getNewsPic());
imageLoader.loadImage(news.getNewsPic(), new ImageLoadingListener() {
#Override
public void onLoadingStarted(String imageUri, View view) {
}
#Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
}
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
mvh.newsImageView.setImageBitmap(loadedImage);
mvh.spinner.setVisibility(View.GONE);
}
#Override
public void onLoadingCancelled(String imageUri, View view) {
}
});
}catch(Exception e){
mvh.newsImageView.setImageDrawable(context.getResources().getDrawable(R.drawable.nopic));
mvh.spinner.setVisibility(View.GONE);
}
}
}, new CustomErrorListener("ERROR"));
return convertView;
}
This is my adapter. My question is if there is a way to remove this delay to show the content? Or is my problem with network or the listview itself?
I just wanna load all the content for once and then the user can scroll up and down without having to refresh the content everytime.
You're loading the content every time getView is called, that's why it's loading like that. Separate the Volley request from the getView, it should be outside of the adapter entirely, not called upon every load of every piece of the list. You have your News Objects, you can pass an ArrayList to the adapter and fill it from there, that will fix your loading issue. Also, you're calling volley in the Main thread instead of a new thread, you should separate the two, and populate the ListView adapter upon completion of the content being loaded.
One, the ViewHolder pattern example should be something more like this:
if (convertView == null) {
convertView = inflater.inflate(R.layout.bigcat_listview,null);
mvh = new myViewHolder();
//... rest of your code
} else {
mvh = (myViewHolder) convertView.getTag();
//... rest of your code
}
Second, the major Volley loading stuff should not be in the adapter, but processed elsewhere beforehand then passed in. This example should help you out a lot.

CustomListview Volley with Image doesn't works in real device

Someone, help me with this problem. i have stuck in 3 days because this problem -_-!
i can make listview with image and text using volley library, its works in emulator (i use genymotion emulator) the image and text show. but when i run it in my device (android Jelly 4.3.0) the listview is empty. the layer is blank (empty). i don't know why.
heres my piece code
public class DaftarBarang_Layout extends Activity{
private List<Produk> produkList = new ArrayList<Produk>();
private ListView listView;
private CustomListAdapter adapter;
private ProgressDialog pDialog;
private ServerRequest serverRequest;
JSONArray member = null;
private static final String url = "http://192.168.117.1:808/Koen_CI/index.php/daftar_barang_control";
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.daftarbarang_layout);
listView = (ListView) findViewById(R.id.list);
adapter = new CustomListAdapter(this, produkList);
listView.setAdapter(adapter);
btnBack = (Button)findViewById(R.id.btnBackDaftarBarang);
setBehavior();
// Creating volley request obj
JsonArrayRequest produkReq = 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);
Produk produk = new Produk();
produk.setNamaProduk(obj.getString("nama_produk"));
produk.setHargaProduk(obj.getString("harga_produk"));
produk.setFotoProduk(obj.getString("foto_produk"));
Log.d("TAG", "TAG : " + produk.getNamaProduk());
// adding movie to movies array
produkList.add(produk);
} 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(produkReq);
}
im sure the url is fine, and image return is http://192.168.117.1:808/Koen_CI/gambarbaju/batik.jpg.
the problem is, why in real device the listview is not show, but in emulator the listview is show..
sorry for my bad english, but thanks anyway.. :)
heres my CustomListAdapter:
public class CustomListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<Produk> produkItems;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public CustomListAdapter(Activity activity, List<Produk> produkItems) {
this.activity = activity;
this.produkItems = produkItems;
}
#Override
public int getCount() {
return produkItems.size();
}
#Override
public Object getItem(int location) {
return produkItems.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 rating = (TextView) convertView.findViewById(R.id.rating);
// getting movie data for the row
Produk p = produkItems.get(position);
// thumbnail image
thumbNail.setImageUrl(p.getFotoProduk(), imageLoader);
// title
title.setText(p.getNamaProduk());
// rating
rating.setText("Harga: " + p.getHargaProduk());
return convertView;
}
Add this code to your onCreate or init method.
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
If this doesn't work please post logcat showing warning or error.

How to fetch the image using JSON in ListFragment?

I am new to android development,I am parsing my data using JSON Parsing method,I extend my class with List Fragment and I want my data in list view but the problem is i am getting all the data perfectly except the images,i don't know how to solve it,my response looks like this
{"matching":[{"name":"Monic Dano","profile_id":"GM335695","image":"http://mywebsitename.com/images/Girlnoimage.jpg","cast":"","age":"24","location":"Ivory Coast"}]}
public class HomeFragment extends ListFragment {
//CustomAdapter adapter;
//private List<RowItem> rowItems;
private ProgressDialog pDialog;
//JSON parser class
JSONParser jsonParser = new JSONParser();
JSONArray matching=null;
ArrayList<HashMap<String,String>> aList;
private static String MATCH_URL = null;
private static final String TAG_MATCH="matching";
private static final String TAG_NAME="name";
private static final String TAG_PROFILE="profile_id";
private static final String TAG_IMAGE="image";
private static final String TAG_CAST="cast";
private static final String TAG_AGE="age";
private static final String TAG_LOCATION="location";
private ListView listview;
public HomeFragment(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String strtext = getArguments().getString("user_login_id");
MATCH_URL = "http://mywebsitename.com/webservice/matching?version=apps&user_login_id="+strtext;
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
aList = new ArrayList<HashMap<String,String>>();
// rowItems = new ArrayList<RowItem>();
listview=(ListView)rootView.findViewById(android.R.id.list);
new LoadAlbums().execute();
return rootView;
}
class LoadAlbums extends AsyncTask<String, String, String> {
/**
* Before starting background thread Show Progress Dialog
* */
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(HomeFragment.this.getActivity());
pDialog.setMessage("Loading...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
protected String doInBackground(String... args) {
ServiceHandler sh = new ServiceHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(MATCH_URL, ServiceHandler.GET);
Log.d("Response: ", "> " + jsonStr);
if (jsonStr != null) {
try {
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
matching = jsonObj.getJSONArray(TAG_MATCH);
// looping through All Contacts
for (int i = 0; i < matching.length(); i++) {
JSONObject c = matching.getJSONObject(i);
// Storing each json item values in variable
String user_name = c.getString(TAG_NAME);
String user_profile=c.getString(TAG_PROFILE);
String user_image=c.getString(TAG_IMAGE);
String user_cast=c.getString(TAG_CAST);
String user_age=c.getString(TAG_AGE);
String user_location=c.getString(TAG_LOCATION);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_NAME,user_name);
map.put(TAG_PROFILE, user_profile);
map.put(TAG_IMAGE, user_image);
map.put(TAG_CAST, user_cast);
map.put(TAG_AGE, user_age+" years");
map.put(TAG_LOCATION, user_location);
// adding HashList to ArrayList
aList.add(map);
}
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("ServiceHandler", "Couldn't get any data from the url");
}
return null;
}
protected void onPostExecute(String file_url) {
super.onPostExecute(file_url);
// dismiss the dialog after getting all albums
if (pDialog.isShowing())
pDialog.dismiss();
// updating UI from Background Thread
/**
* Updating parsed JSON data into ListView
* */
// updating listview
CustomAdapter adapter = new CustomAdapter(getActivity(),aList);
setListAdapter(adapter);
}
}
}
Try to AndroidQuery with custom adapter :
public class CustomAdapter extends BaseAdapter {
private Context context;
private ArrayList<HashMap<String,String>> listData;
private AQuery aQuery;
private static final String TAG_NAME="name";
private static final String TAG_PROFILE="profile_id";
private static final String TAG_IMAGE="image";
private static final String TAG_CAST="cast";
private static final String TAG_AGE="age";
private static final String TAG_LOCATION="location";
public CustomAdapter(Context context,ArrayList<HashMap<String,String>> listData) {
this.context = context;
this.listData=listData;
aQuery = new AQuery(this.context);
}
#Override
public int getCount() {
return listData.size();
}
#Override
public Object getItem(int position) {
return listData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
convertView = LayoutInflater.from(context).inflate(R.layout.list_item, null);
holder.propic = (ImageView) convertView.findViewById(R.id.propic);
holder.txtproname = (TextView) convertView.findViewById(R.id.txtproname);
holder.txtproid = (TextView) convertView.findViewById(R.id.txtproid);
holder.txtprofilecast = (TextView) convertView.findViewById(R.id.txtprofilecast);
holder.txtprofileage = (TextView) convertView.findViewById(R.id.txtprofileage);
holder.txtprofileplace = (TextView) convertView.findViewById(R.id.txtprofileplace);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
holder.txtproname.setText(listData.get(position).get(TAG_NAME));
holder.txtproid.setText(listData.get(position).get(TAG_PROFILE));
holder.txtprofilecast.setText(listData.get(position).get(TAG_CAST));
holder.txtprofileage.setText(listData.get(position).get(TAG_AGE));
holder.txtprofileplace.setText(listData.get(position).get(TAG_LOCATION));
aQuery.id(holder.propic).image(listData.get(position).get(TAG_IMAGE),true,true,0,R.drawable.ic_launcher);
// image parameter : 1 : memory cache,2:file cache,3:target width,4:fallback image
return convertView;
}
class ViewHolder{
ImageView propic;
TextView txtproname;
TextView txtproid;
TextView txtprofilecast;
TextView txtprofileage;
TextView txtprofileplace;
}
}
How to set adapter to ListView :
CustomAdapter adapter = new CustomAdapter(getActivity(),aList);
setListAdapter(adapter);
You can use universal image loader for viewing images from your server.Z
Just pass the image url and your view and you are good to go.
For your reference here is the link to Universal Image loader with all its documentation.
https://github.com/nostra13/Android-Universal-Image-Loader
Hop it helps you.
I am hardly suggest you to use Android Query for this. Its mind blowing api given by Android itself. You can download image, download bitmap or whatever you wanna do you can.
You can download the jar file from here :here Download the jar file and set jar to your Build Path.
AQuery androidAQuery=new AQuery(this);
As an example to load image directly from url:
androidAQuery.id(YOUR IMAGEVIEW).image(YOUR IMAGE TO LOAD, true, true, getDeviceWidth(), ANY DEFAULT IMAGE YOU WANT TO SHOW);
As an example to get Bitmap from url:
androidAQuery.ajax(YOUR IMAGE URL,Bitmap.class,0,new AjaxCallback<Bitmap>(){
#Override
public void callback(String url, Bitmap object, AjaxStatus status) {
super.callback(url, object, status);
//You will get Bitmap from object.
}
});
It's very fast and accurate, and using this you can find many more features like Animation when loading; getting a bitmap, if needed; etc.
//Declare adapter globally.
private EfficientAdapter adapter;
//Initialize it in onCreate() method
adapter = new EfficientAdapter(this);
//Set your adapter like
listview.setAdapter(adapter);
//Adapter class code
private class EfficientAdapter extends BaseAdapter {
private LayoutInflater mInflater;
private Context context;
public EfficientAdapter(Context context) {
mInflater = LayoutInflater.from(context);
this.context = context;
}
#Override
public int getCount() {
return aList.size();
}
#Override
public Object getItem(int arg0) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.YOUR ITEM LAYOUT, null);
holder = new ViewHolder();
holder.txtName = (TextView) convertView.findViewById(R.id.txtName);
holder.txtProfile = (TextView) convertView.findViewById(R.id.txtProfile);
holder.txtCast = (TextView) convertView.findViewById(R.id.txtCast);
holder.txtAge = (ImageView) convertView.findViewById(R.id.txtAge);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.txtName.setText(aList.get(position).get(TAG_NAME));
holder.txtProfile.setText(aList.get(position).get(TAG_PROFILE));
holder.txtCast.setText(aList.get(position).get(TAG_CAST));
holder.txtAge.setText(aList.get(position).get(TAG_AGE));
aQuery.id(holder.imgUser).image(data.get(position).get(TAG_IMAGE), true, true);
return convertView;
}
class ViewHolder {
TextView txtName;
TextView txtProfile;
TextView txtCast;
TextView txtAge;
ImageView imgUser;
}
}
In source code of SimpleAdapter:
private void bindView(int position, View view) {
final Map dataSet = mData.get(position);
if (dataSet == null) {
return;
}
final ViewBinder binder = mViewBinder;
final String[] from = mFrom;
final int[] to = mTo;
final int count = to.length;
for (int i = 0; i < count; i++) {
final View v = view.findViewById(to[i]);
if (v != null) {
final Object data = dataSet.get(from[i]);
String text = data == null ? "" : data.toString();
if (text == null) {
text = "";
}
boolean bound = false;
if (binder != null) {
bound = binder.setViewValue(v, data, text);
}
if (!bound) {
if (v instanceof Checkable) {
if (data instanceof Boolean) {
((Checkable) v).setChecked((Boolean) data);
} else if (v instanceof TextView) {
// Note: keep the instanceof TextView check at the bottom of these
// ifs since a lot of views are TextViews (e.g. CheckBoxes).
setViewText((TextView) v, text);
} else {
throw new IllegalStateException(v.getClass().getName() +
" should be bound to a Boolean, not a " +
(data == null ? "<unknown type>" : data.getClass()));
}
} else if (v instanceof TextView) {
// Note: keep the instanceof TextView check at the bottom of these
// ifs since a lot of views are TextViews (e.g. CheckBoxes).
setViewText((TextView) v, text);
} else if (v instanceof ImageView) {
if (data instanceof Integer) {
setViewImage((ImageView) v, (Integer) data);
} else {
setViewImage((ImageView) v, text);
}
} else {
throw new IllegalStateException(v.getClass().getName() + " is not a " +
" view that can be bounds by this SimpleAdapter");
}
}
}
}
}
You can see if your view is ImageView , the code will use the url String be the resId in
/**
* Called by bindView() to set the image for an ImageView but only if
* there is no existing ViewBinder or if the existing ViewBinder cannot
* handle binding to an ImageView.
*
* By default, the value will be treated as an image resource. If the
* value cannot be used as an image resource, the value is used as an
* image Uri.
*
* This method is called instead of {#link #setViewImage(ImageView, int)}
* if the supplied data is not an int or Integer.
*
* #param v ImageView to receive an image
* #param value the value retrieved from the data set
*
* #see #setViewImage(ImageView, int)
*/
public void setViewImage(ImageView v, String value) {
try {
v.setImageResource(Integer.parseInt(value));
} catch (NumberFormatException nfe) {
v.setImageURI(Uri.parse(value));
}
}
And your error is here , so you need Override the getView function of SimpleAdapter.Here is code:
Uri uri = Uri.parse("http://gujjumatch.com/images/Girlnoimage.jpg");
image.setImageURI(uri);
You need to create adapter and extend it to BaseAdapter and add all your items and call it in your AsyncTask's method and it will return your output as said by Haresh Chellana.

Selecting item from ListView (Json Data)

I'm trying to implement a simple android REST Client and i having some problems understanding how to pass data between my activities.
I have this ListActivity (I'm using the Spring REST Template) :
public class MainActivity extends ListActivity
{
protected static final String TAG = MainActivity.class.getSimpleName();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Toast.makeText(this, "You have selected" + position + id ,
Toast.LENGTH_SHORT).show();
}
#Override
protected void onStart() {
super.onStart();
new DownloadClientesTask().execute();
}
private void refreshClientes(List<Cliente> clientes) {
if (clientes == null) {
return;
}
ClientesListAdapter adapter = new ClientesListAdapter(this, clientes);
setListAdapter(adapter);
}
private class DownloadClientesTask extends AsyncTask<Void, Void, List<Cliente>> {
#Override
protected List<Cliente> doInBackground(Void... params) {
final String url = "http://192.168.1.119/~henry/api_slim/index.php/customers";
try {
// Set the Accept header for "application/json"
HttpHeaders requestHeaders = new HttpHeaders();
List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
acceptableMediaTypes.add(MediaType.APPLICATION_JSON);
requestHeaders.setAccept(acceptableMediaTypes);
// Populate the headers in an HttpEntity object to use for the request
HttpEntity<?> requestEntity = new HttpEntity<Object>(requestHeaders);
// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
// Perform the HTTP GET request
ResponseEntity<Cliente[]> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity,
Cliente[].class);
// convert the array to a list and return it
return Arrays.asList(responseEntity.getBody());
} catch (Exception e) {
// TODO Auto-generated catch block
Log.e(TAG, e.getMessage(), e);
}
return null;
}
#Override
protected void onPostExecute(List<Cliente> result) {
refreshClientes(result);
}
}
}
And this is My listAdapter :
public class ClientesListAdapter extends BaseAdapter{
private List<Cliente> clientes;
private final LayoutInflater layoutInflater;
public ClientesListAdapter(Context context, List<Cliente> clientes) {
this.clientes = clientes;
this.layoutInflater = LayoutInflater.from(context);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return this.clientes != null ? clientes.size() : 0;
}
#Override
public Cliente getItem(int position) {
return this.clientes.get(position);
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = this.layoutInflater.inflate(R.layout.cliente_list_item, parent, false);
}
Cliente cliente = getItem(position);
if (cliente != null) {
TextView t = (TextView) convertView.findViewById(R.id.name);
t.setText(cliente.getFirstname());
}
return convertView;
}
}
This the POJO class of the data iḿ getting :
public class Cliente {
private Integer id_customer;
private String firstname;
public Integer getId_customer() {
return id_customer;
}
public void setId_customer(Integer id_customer) {
this.id_customer = id_customer;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
}
When i select an element from the listView i would like show details specific about this element on another activity or fragment, but i don't know how to obtain the customer_id of this element from the list, do i have to save it when i procesing the response? do I need to use content provider or database provide this behavior? i'm really confused, thanks in advance for any help!
There are good examples on how to pass data from one activity to another here, pass objects between activities. You may want to take a look first to the solutions on those links.
Please see below an example that can put you on the right track.
List adapter class:
public class ClientesListAdapter extends BaseAdapter{
//private members
private List<Cliente> clientes;
//adapter position - not used for this example
public int adapterPosition;
//context of app
private Context mContext;
//default constructor
public ClientesListAdapter(Context context, List<Cliente> clientes) {
//context pointer
this.mContext = context;
//alloc
this.clientes = new ArrayList<Cliente>(clientes.size());
this.clientes.addAll(clients);
}
//Holder for events and dates (memory management)
public static class ViewHolder{
TextView myTextView;//this is actually findViewById(R.id.name) #see getView() method
}
//generated method
#Override
public int getCount() {
// TODO Auto-generated method stub
return this.clientes != null ? clientes.size() : 0;
}
//generated method
#Override
public Cliente getItem(int position) {
return this.clientes.get(position);
}
//generated method
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
//get client's id
public int getClienteId(int position){
return this.clientes.get(position).getClienteId();
}
//get client's id without passing the position
public int getClienteId(){
return this.clientes.get(adapterPosition).getClienteId();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//row is actually convertView (the current view)
View row = convertView;
//holds our view elements
ViewHolder holder;
//if row is null
if(row == null){
//inflate layout to get our view elements
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(com.yourapp.R.layout.my_layout, parent, false);//your layout here, modify code
//set up the holder
holder = new ViewHolder();
holder.myTextView = (TextView) row.findViewById(com.yourapp.R.id.name);
//give the row a tag (holder)
row.setTag(holder);
}else{
//row is not null we can see it (no need to allocate memory)
holder = (ViewHolder) row.getTag();
}
//get your cliente object
Cliente cliente = this.clientes.get(position);
if (cliente != null) {
holder.myTextView.setText(cliente.getFirstname());
}
//copy position
adapterPostion = position;
return convertView;
}
}
You see that we used a ViewHolder class for memory management. This is a good practice for holding view elements inside your list adapter. You can find more info about list views, explained by Romain Guy - The World of ListViews.
From your MainActivity allocate the adapter and get your item on click:
//---- code --- //
ListView myListView = (ListView)findViewById(R.id.mylistview);//or you may use ListActivity
ClientesListAdapter adapter = new ClientesListAdapter(this, clientes);//"this" or "getApplicationContext()"
myListView.setAdapter(adapter);
adapter.notifyDataSetChanged();//notify
// ---- code --- //
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Toast.makeText(this, "You have selected" + position + id ,
Toast.LENGTH_SHORT).show();
Intent intent = new Intent(MyActivity.this, ActivityB.class);
intent.putInt("cliente_id",adapter.getClienteId());
startActivity(intent);
}
Another example is with implementing an interface in the adapter like this:
//--code//
//Interface method
private OnSaveEditsListener saveEditsListener = null;
public void setOnSaveEditsListener(OnSaveEditsListener l) {
saveEditsListener = l;
}
//--code//
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
//--code--//
//get clicked position of calendar (get clicked day)
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
v.requestFocusFromTouch();
currentAgendaPosition = position;
try{
saveEditsListener.onSaveEdits();
}catch(Exception ex){
ex.printStackTrace();
}
}
});
//returns current row
return row;
}
//--code--//
And from your MainActivity start the second activity like this:
adapter.setOnSaveEditsListener(new OnSaveEditsListener() {
#Override
public void onSaveEdits() {
//Start activity from here
//--code--//
startActivity(intent);
}
});
get the position of the item clicked and get the object present at that position from the arraylist and use it to get the required details.
use
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Toast.makeText(this, "You have selected" + position + id ,
Toast.LENGTH_SHORT).show();
// use this.clientes.get(position) and pass it to the next activity or fragment using putextras to where you need to pass and display this in the destination end using the same object by getting it using getExtra()
}
Your list is in the adapter:
private List<Cliente> clientes;
In onListItemClick, you can get the Cliente from this list using the position parameter.
You pass information to another activity when you call startActivity, passing it an Intent. The Intent may have additional information, in your case you could set the customer_id as an int extra, something like:
intent.putExtra(EXTRA_CUSTOMER_ID, customer_id);

Categories

Resources