Reputation: 613
I have an app that loads the traffic report from a server and shows it in a timeline (like twitter), the app is configured to load the data from the server every 10 seconds using this code:
@Override
public void onResume() {
super.onResume();
autoUpdate = new Timer();
autoUpdate.schedule(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
new DownloadJSON2().execute(); // this is the class that downloads the data from the server.
}
});
}
}, 0, 10000); // updates each 10 secs
}
@Override
public void onPause() {
autoUpdate.cancel();
super.onPause();
}
The problem is that if I scroll down the list and I'm reading the older posts, the list refreshes and send me to the top of it. I want to download that data like ajax and append it to the top. Or just to tell me that is X new reports and a button to show it.
How can I acomplish this?
BTW I'm extremely new to android programming.
Thanks in advance.
EDIT: Thanks to Vasily Sochinsky i've added the following:
public class DownloadJSON extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
// Create a progressdialog
mProgressDialog = new ProgressDialog(MainActivity.this);
// Set progressdialog title
mProgressDialog.setTitle("Cargando reportes en tiempo real");
// Set progressdialog message
mProgressDialog.setMessage("Por favor espere");
mProgressDialog.setIndeterminate(false);
// Show progressdialog
mProgressDialog.show();
}
@Override
protected Void doInBackground(Void... params) {
// Create an array
arraylist = new ArrayList<HashMap<String, String>>();
// Retrieve JSON Objects from the given URL address
jsonobject = JSONfunctions
.getJSONfromURL("http://server.com/timeline.php");
try {
// Locate the array name in JSON
jsonarray = jsonobject.getJSONArray("datos");
for (int i = 0; i < jsonarray.length(); i++) {
HashMap<String, String> map = new HashMap<String, String>();
jsonobject = jsonarray.getJSONObject(i);
// Retrive JSON Objects
// jsonobject1 = jsonobject.getJSONObject("contenido");
map.put("imagen", jsonobject.getString("imagen"));
map.put("quien", jsonobject.getString("quien"));
map.put("fecha", jsonobject.getString("fecha"));
map.put("reporte", jsonobject.getString("reporte"));
// map.put("imgs", jsonobject1.getString("imgs"));
// map.put("video", jsonobject1.getString("video"));
// Set the JSON Objects into the array
arraylist.add(map);
}
} catch (JSONException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void args) {
// Locate the listview in listview_main.xml
listview = (ListView) findViewById(R.id.listview);
// Pass the results into ListViewAdapter.java
adapter = new ListViewAdapter(MainActivity.this, arraylist);
// Set the adapter to the ListView
listview.setAdapter(adapter);
adapter.notifyDataSetChanged();
// Close the progressdialog
mProgressDialog.dismiss();
}
}
But the listview is not updating with the new data, how can i achieve this?
EDIT 2: Thanks to cogentapps that gave me a solution, but i still can not add it to the code, where should i add it?
I've tried this but eclipse shows many errors:
protected void onPostExecute(Void args) {
// Locate the listview in listview_main.xml
listview = (ListView) findViewById(R.id.listview);
// Pass the results into ListViewAdapter.java
adapter = new ListViewAdapter(MainActivity.this, arraylist);
// Set the adapter to the ListView
adapter.addAll();
listview.notifyDataSetChanged();
// Close the progressdialog
mProgressDialog.dismiss();
}
This is the code from my ListViewAdapter, where should i add the adapter.add()?
public class ListViewAdapter extends BaseAdapter {
// Declare Variables
Context context;
LayoutInflater inflater;
ArrayList<HashMap<String, String>> data;
ImageLoader imageLoader;
HashMap<String, String> resultp = new HashMap<String, String>();
String coment;
public String img;
public int imga;
public ListViewAdapter(Context context,
ArrayList<HashMap<String, String>> arraylist) {
this.context = context;
data = arraylist;
imageLoader = new ImageLoader(context);
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
public View getView(final int position, View convertView, ViewGroup parent) {
// Declare Variables
TextView quien;
ImageView imagen;
TextView reporte;
TextView fecha;
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.listview_item, parent, false);
// Get the position
resultp = data.get(position);
// Locate the TextViews in listview_item.xml
// Locate the ImageView in listview_item.xml
imagen = (ImageView) itemView.findViewById(R.id.imagen);
fecha = (TextView) itemView.findViewById(R.id.fecha);
quien = (TextView) itemView.findViewById(R.id.quien);
reporte = (TextView) itemView.findViewById(R.id.reporte);
// Capture position and set results to the TextViews
// Capture position and set results to the ImageView
// Passes flag images URL into ImageLoader.class
imageLoader.DisplayImage(resultp.get(MainActivity.IMAGEN), imagen);
fecha.setText(resultp.get(MainActivity.FECHA));
reporte.setText(resultp.get(MainActivity.REPORTE));
quien.setText(resultp.get(MainActivity.QUIEN));
// Capture ListView item click
/*
itemView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// Get the position
resultp = data.get(position);
Intent intent = new Intent(context, SingleItemView.class);
// Pass all data rank
intent.putExtra("imagen", resultp.get(MainActivity.IMAGEN));
intent.putExtra("quien", resultp.get(MainActivity.QUIEN));
intent.putExtra("fecha", resultp.get(MainActivity.FECHA));
// Start SingleItemView Class
context.startActivity(intent);
}
});
*/
return itemView;
}
}
Upvotes: 0
Views: 5333
Reputation: 1636
Take a look at the answer to this question for an explanation / example of how to maintain scroll position after adding items to a list: Retaining position in ListView after calling notifyDataSetChanged
Basically, you make a note of the position and scroll offset of the first visible item in the list before adding new data. Then afterwards, you restore the previous position and scroll offset.
However, because you're adding new items at the top of the list, the position returned by getFirstVisiblePosition()
may refer to a different item after refreshing. The item that was at position 0 before refreshing may now be position 10. To fix that, you need to determine the number of new items returned by timeline.php
and add it to index
, like this:
mList.setSelectionFromTop(index + newItemCount, top);
You could probably determine which items are new by comparing the date field.
(By the way, if timeline.php
only returns the most recent set of items, you could run into trouble if the user has scrolled to an older item which is no longer returned by timeline.php
. After setting the new data, the old item will no longer be present, so you won't be able to scroll to it.
To fix that, you could keep the old ArrayList
around and only add new items to it in doInBackground()
. And call notifyDataSetChanged()
in doInBackground()
. That way, the adapter will still have access to older items.)
Upvotes: 1