Android - ListView - lags - android

I have a problem with an application on android. More specifically, I have a problem with lagging ListView. I use class ViewHolder. Actually I do not display a lot of things, but my move Items with large lags.
I do not know what I could change, I tried to found answers in search but found no solution to this problem.
I can scroll my view, but in interval few seconds my view stop for 2 sec. I thought that it is problem with update adapter, but i don't know what can i do change.
Sorry for my English.
Here is the code of the adapter:
public class ListAdapter_obiekty extends BaseAdapter{
Context ctx;
LayoutInflater lInflater;
private int screenHeight;
ArrayList<HashMap<String, String>> products,dane;
ListAdapter_obiekty(Context context, ArrayList<HashMap<String, String>> data) {
ctx = context;
this.products = data;
lInflater = (LayoutInflater) ctx
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
screenHeight = metrics.heightPixels;
}
#Override
public int getCount() {
return products == null ? 0 : products.size();
}
#Override
public Object getItem(int position) {
return products.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public void updateItem(final String name, final String item, final Integer pos) {
HashMap<String,String> hm = this.products.get(pos);
hm.put(name, item);
this.products.set(pos,hm);
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
HashMap<String, String> hm = this.products.get(position);
String tryb = hm.get("tryb");
ListViewHolder holder = null;
if (view == null) {
view = lInflater.inflate(R.layout.list_item, parent, false);
ViewGroup.LayoutParams params = view.getLayoutParams();
if (params.height != screenHeight) params.height = screenHeight/2;
view.setLayoutParams(params);
holder = new ListViewHolder();
holder.tryb = ((TextView) view.findViewById(R.id.tV_tryb));
view.setTag(holder);
}else{
holder = (ListViewHolder) view.getTag();
}
if (position % 2 == 0) {
view.setBackgroundResource(R.drawable.lista_obiekty_niebieski);
holder.tryb.setTextColor(Color.parseColor("#e3e9e4"));
}else{
view.setBackgroundResource(R.drawable.lista_obiekty_pod_logo);
holder.tryb.setTextColor(Color.parseColor("#007bb3"));
}
holder.tryb.setText(hm.get(ctx.getString(R.string.tryb)));
return view;
}
static class ListViewHolder{
TextView tryb;
}
}
Here is the code to create an adapter and update:
runOnUiThread(new Runnable() {
public void run() {
adapter = new ListAdapter_obiekty(HomeActivity.this, productsListNAZWY,productsListDANE);
ListView lvMain = (ListView) findViewById(R.id.list);
lvMain.setAdapter(adapter);
for(int i =0; i<=ile; i++){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
HashMap news = null;
news = (HashMap) productsListNAZWY.get(i);
String ip = (String) news.get("numer_ip");
callAsynchronousTask(i, "http://" + ip + "/config/xml.cgi?A|1|74|I|1|29|D|1|62");
Log.d("TAGS","URUCHOMILEM");
}
}
And Here is my function callAsynchronousTask() :
public void callAsynchronousTask(final int i, final String numerIPx) {
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
obiekt=null;
obiekt = new ListaXML();
String[] tabAnal = obiekt.execute(numerIPx).get();
Integer code = obiekt.code;
String trybPracy = "";
trybPracy = tabAnal[10];
HashMap maps = new HashMap<String,String>();
... more items (5-6)
maps.put("trybPracy", trybPracy);
adapter.updateItem(maps,i);
} catch (Exception e) {
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 5000);
}

I suspect the lag is due to this bit of the code
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
You're doing this in the main UI thread.
Reduce this time to 100 and see what happens. If it is the cause you will have to re-work your code, as there doesn't seem to be anything wrong with your list adapter.
Edit: comment out this bit of code to find the lag.
for(int i =0; i<=ile; i++){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
HashMap news = null;
news = (HashMap) productsListNAZWY.get(i);
String ip = (String) news.get("numer_ip");
callAsynchronousTask(i, "http://" + ip + "/config/xml.cgi?A|1|74|I|1|29|D|1|62");
Log.d("TAGS","URUCHOMILEM");
}

Related

The textview is not stable in custom listview android

actually I Have a custom listview which contains a countdown timer and the countdown timer is created by a handler, now the list loads fine and everything seems to be correct but when I start to scroll the countdown timer becomes shaky and unstable the values seems to overlap each other means the lastrow values are printed in the first row and things like that, the values are up and down and it does not work properly, here the API sends a long value which is passed to handler and the handler converts that to a countdown timer, so where does the problem lies , whenever I refresh the list it becomes all fine, but as I start scrolling the same problem comes again.. here is my code
public class fixtures extends Fragment {
private ListView fixtureListView;
String Balance,userEmail;
SwipeRefreshLayout mSwipeRefreshLayout;
private static final String FORMAT = "%02d:%02d:%02d";
List<ListView_fixture_conveyer> fixture_conveyerList;
ListView_fixture_conveyer fixtureList;
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup viewGroup, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fixtures, viewGroup, false);
fixtureListView = view.findViewById(R.id.fixture_list);
mSwipeRefreshLayout = view.findViewById(R.id.swipeToRefresh);
User user = SharedPrefManager.getInstance(getActivity()).getUser();
userEmail= user.getEmail();
new JSONTask().execute("http://www.judgement6.com/judgement_files/fixture_json.php");
DisplayImageOptions options = new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisk(true)
.build();
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(Objects.requireNonNull(getActivity()))
.defaultDisplayImageOptions(options)
.build();
com.nostra13.universalimageloader.core.ImageLoader.getInstance().init(config);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
fixture_conveyerList.clear();
new JSONTask().execute("http://www.judgement6.com/judgement_files/fixture_json.php");
mSwipeRefreshLayout.setRefreshing(false);
}
});
return view;
}
#SuppressLint("StaticFieldLeak")
public class JSONTask extends AsyncTask<String, String, List<ListView_fixture_conveyer>> {
ProgressDialog loading;
#Override
protected void onPreExecute() {
super.onPreExecute();
loading = ProgressDialog.show(getActivity(), "loading,please wait...", null, true, true);
}
#Override
protected List<ListView_fixture_conveyer> doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder buffer = new StringBuilder();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String finalJson = buffer.toString();
JSONObject parentObject = new JSONObject(finalJson);
JSONArray parentArray = parentObject.getJSONArray("list");
fixture_conveyerList = new ArrayList<ListView_fixture_conveyer>();
for (int i = 0; i < parentArray.length(); i++) {
JSONObject finalObject = parentArray.getJSONObject(i);
Log.e("fixtureObject",finalObject.toString());
fixtureList = new ListView_fixture_conveyer();
fixtureList.setTournament(finalObject.getString("tournament"));
fixtureList.setTeam1_photo(finalObject.getString("team1_photo"));
fixtureList.setTeam2_photo(finalObject.getString("team2_photo"));
fixtureList.setTeam1_name(finalObject.getString("team1_name"));
fixtureList.setTeam2_name(finalObject.getString("team2_name"));
fixtureList.setTime(finalObject.getString("Time"));
fixture_conveyerList.add(fixtureList);
}
return fixture_conveyerList;
} catch (IOException | JSONException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(List<ListView_fixture_conveyer> result) {
super.onPostExecute(result);
if (result !=null) {
loading.dismiss();
ListAdapter adapter = new ListAdapter(getActivity(), R.layout.custom_list_fixture, result);
fixtureListView.setAdapter(adapter);
}
else
{
Toast.makeText(getActivity(), "No Internet Connection!", Toast.LENGTH_LONG).show();
loading.dismiss();
}
}
}
public class ListAdapter extends ArrayAdapter {
private List<ListView_fixture_conveyer> fixture_conveyerList;
private int resource;
private LayoutInflater inflater;
ListAdapter(Context context, int resource, List<ListView_fixture_conveyer> objects) {
super(context, resource, objects);
fixture_conveyerList = objects;
this.resource = resource;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getViewTypeCount() {
return getCount();
}
#Override
public int getItemViewType(int position) {
return position;
}
#NonNull
#Override
public View getView(final int position, View convertView, #NonNull ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(resource, null);
}
final TextView team1_name,team2_name;
final TextView tournament,time;
ImageView team1_photo,team2_photo;
team1_photo = convertView.findViewById(R.id.team1);
team2_photo = convertView.findViewById(R.id.team2);
team1_name = convertView.findViewById(R.id.team1_name);
team2_name = convertView.findViewById(R.id.team2_name);
tournament= convertView.findViewById(R.id.tournament);
time= convertView.findViewById(R.id.timecounter);
ImageLoader.getInstance().displayImage(fixture_conveyerList.get(position).getTeam1_photo(), team1_photo);
ImageLoader.getInstance().displayImage(fixture_conveyerList.get(position).getTeam2_photo(), team2_photo);
team1_name.setText(fixture_conveyerList.get(position).getTeam1_name());
team2_name.setText(fixture_conveyerList.get(position).getTeam2_name());
tournament.setText(fixture_conveyerList.get(position).getTournament());
time.setText(fixture_conveyerList.get(position).getTime());
Log.e("mytimer",fixture_conveyerList.get(position).getTime());
if (!("false").equals(fixture_conveyerList.get(position).getTime())){
Log.e("inside_mytimer",fixture_conveyerList.get(position).getTime());
long newValue=Long.parseLong(fixture_conveyerList.get(position).getTime());
new CountDownTimer(newValue, 1000) {
#SuppressLint({"DefaultLocale", "SetTextI18n"})
public void onTick(long millisUntilFinished) {
time.setText("" + String.format(FORMAT,
TimeUnit.MILLISECONDS.toHours(millisUntilFinished),
TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished) - TimeUnit.HOURS.toMinutes(
TimeUnit.MILLISECONDS.toHours(millisUntilFinished)),
TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) - TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished))));
}
public void onFinish() {
time.setText("Fixture closed");
}
}.start();
}
else{
time.setText("Fixture closed");
}
return convertView;
}
}
}
Here is my model class code
public class ListView_fixture_conveyer {
private String tournament;
private String team1_photo;
private String team2_photo;
private String team1_name;
private String team2_name;
private String time;
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getTeam1_name() {
return team1_name;
}
public void setTeam1_name(String team1_name) {
this.team1_name = team1_name;
}
public String getTeam2_name() {
return team2_name;
}
public void setTeam2_name(String team2_name) {
this.team2_name = team2_name;
}
public String getTournament() {
return tournament;
}
public void setTournament(String tournament) {
this.tournament = tournament;
}
public String getTeam1_photo() {
return team1_photo;
}
public void setTeam1_photo(String team1_photo) {
this.team1_photo = team1_photo;
}
public String getTeam2_photo() {
return team2_photo;
}
public void setTeam2_photo(String team2_photo) {
this.team2_photo = team2_photo;
}
}
Edit (Tested)
---> For Timer issue , you need to take time variable in your class and update variable with Handler use it with reload data. Like,
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
for (int i = 0, dataLength = fixture_conveyerList.size(); i < dataLength; i++) {
ListView_fixture_conveyer item = fixture_conveyerList.get(i);
item.timeRemaining -= 1000;
}
adapter.notifyDataSetChanged();
timerHandler.postDelayed(this, 1000); //run every Second
}
};
List Adapter Class
public class ListAdapter extends ArrayAdapter {
private List<ListView_fixture_conveyer> fixture_conveyerList;
private int resource;
private LayoutInflater inflater;
ViewHolder holder;
ListAdapter(Context context, int resource, List<ListView_fixture_conveyer> objects) {
super(context, resource, objects);
fixture_conveyerList = objects;
this.resource = resource;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
timerHandler.postDelayed(timerRunnable, 50); //start unique timer
}
#Override
public int getViewTypeCount() {
return getCount();
}
#Override
public int getItemViewType(int position) {
return position;
}
#NonNull
#Override
public View getView(final int position, View convertView, #NonNull ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(resource, null);
holder = new ViewHolder();
holder.team1_photo = convertView.findViewById(R.id.team1);
holder.team2_photo = convertView.findViewById(R.id.team2);
holder.team1_name = convertView.findViewById(R.id.team1_name);
holder.team2_name = convertView.findViewById(R.id.team2_name);
holder.tournament = convertView.findViewById(R.id.tournament);
holder.time = convertView.findViewById(R.id.timecounter);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
ImageLoader.getInstance().displayImage(fixture_conveyerList.get(position).getTeam1_photo(), holder.team1_photo);
ImageLoader.getInstance().displayImage(fixture_conveyerList.get(position).getTeam2_photo(), holder.team2_photo);
holder.team1_name.setText(fixture_conveyerList.get(position).getTeam1_name());
holder.team2_name.setText(fixture_conveyerList.get(position).getTeam2_name());
holder.tournament.setText(fixture_conveyerList.get(position).getTournament());
holder.time.setText(fixture_conveyerList.get(position).timeRemaining);
Log.e("mytimer", fixture_conveyerList.get(position).getTime());
if (!("false").equals(fixture_conveyerList.get(position).getTime())) {
Log.e("inside_mytimer", fixture_conveyerList.get(position).getTime());
long newValue = fixture_conveyerList.get(position).timeRemaining;
if (newValue > 0) {
holder.time.setText(String.format(FORMAT,
TimeUnit.MILLISECONDS.toHours(newValue),
TimeUnit.MILLISECONDS.toMinutes(newValue) - TimeUnit.HOURS.toMinutes(
TimeUnit.MILLISECONDS.toHours(newValue)),
TimeUnit.MILLISECONDS.toSeconds(newValue) - TimeUnit.MINUTES.toSeconds(
TimeUnit.MILLISECONDS.toMinutes(newValue))));
} else {
holder.time.setText("Fixture closed");
}
} else {
holder.time.setText("Fixture closed");
}
return convertView;
}
}

Fail to AsyncTask update progressBar's progress when first enter the fragment ListView, then okay after scroll ListView

The progressbar cannot show progress if without scroll down and back to same position visit again, detail please check this demo:
https://www.youtube.com/watch?v=wGu8MyUHidQ&feature=youtu.be
No exception or error, maybe ListView bug or logic error, anyone have any idea?
DownloadInfo class:
private final static String TAG = DownloadInfo.class.getSimpleName();
public enum DownloadState {
NOT_STARTED,
QUEUED,
DOWNLOADING,
COMPLETE
}
private volatile DownloadState mDownloadState = DownloadState.NOT_STARTED;
private final String mFilename;
private volatile Integer mProgress;
private final Integer mFileSize;
private volatile ProgressBar mProgressBar;
public DownloadInfo(String filename, Integer size) {
mFilename = filename;
mProgress = 0;
mFileSize = size;
mProgressBar = null;
}
//Follow by getters & setters
DownloadInfoArrayAdapter Class:
public class DownloadInfoArrayAdapter extends ArrayAdapter<DownloadInfo> {
private static class ViewHolder {
TextView textView;
ProgressBar progressBar;
Button button;
DownloadInfo info;
}
public DownloadInfoArrayAdapter(Context context, List<DownloadInfo> objects) {
super(context, objects);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
final DownloadInfo info = getItem(position);
ViewHolder holder = null;
if (null == row) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.file_download_row, parent, false);
holder = new ViewHolder();
holder.textView = (TextView) row.findViewById(R.id.downloadFileName);
holder.progressBar = (ProgressBar) row.findViewById(R.id.downloadProgressBar);
holder.button = (Button) row.findViewById(R.id.downloadButton);
holder.info = info;
row.setTag(holder);
} else {
holder = (ViewHolder) row.getTag();
holder.info.setProgressBar(null);
holder.info = info;
holder.info.setProgressBar(holder.progressBar);
}
holder.textView.setText(info.getFilename());
holder.progressBar.setProgress(info.getProgress());
holder.progressBar.setMax(info.getFileSize());
info.setProgressBar(holder.progressBar);
holder.button.setEnabled(info.getDownloadState() == DownloadState.NOT_STARTED);
final Button button = holder.button;
holder.button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
info.setDownloadState(DownloadState.QUEUED);
button.setEnabled(false);
button.invalidate();
FileDownloadTask task = new FileDownloadTask(info);
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
});
return row;
}
}
FileDownloadTask class:
#Override
protected void onProgressUpdate(Integer... values) {
mInfo.setProgress(values[0]);
ProgressBar bar = mInfo.getProgressBar();
if (bar != null) {
bar.setProgress(mInfo.getProgress());
bar.invalidate();
}
}
#Override
protected Void doInBackground(Void... params) {
Log.d(TAG, "Starting download for " + mInfo.getFilename());
mInfo.setDownloadState(DownloadState.DOWNLOADING);
for (int i = 0; i <= mInfo.getFileSize(); ++i) {
try {
Thread.sleep(16);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress(i);
}
mInfo.setDownloadState(DownloadState.COMPLETE);
return null;
}
#Override
protected void onPostExecute(Void result) {
mInfo.setDownloadState(DownloadState.COMPLETE);
}
#Override
protected void onPreExecute() {
mInfo.setDownloadState(DownloadState.DOWNLOADING);
}
In the fragment add click listener
lvStickerGroup = (ListView) activity.findViewById(R.id.lvStickerGroup);
List<DownloadInfo> downloadInfo = new ArrayList<DownloadInfo>();
for (int i = 0; i < 50; ++i) {
downloadInfo.add(new DownloadInfo("File " + i, 1000));
}
adapter = new DownloadInfoArrayAdapter(activity, downloadInfo);
lvStickerGroup.setAdapter(adapter);
lvStickerGroup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(activity, "bla" + i, Toast.LENGTH_SHORT).show();
}
});
//Testing all below, no luck
((BaseAdapter) adapter).notifyDataSetChanged();
lvStickerGroup.invalidate();
lvStickerGroup.invalidateViews();
lvStickerGroup.refreshDrawableState();
lvStickerGroup.post(new Runnable() {
public void run() {
for (int a = 0; a < lvStickerGroup.getCount(); a++) {
lvStickerGroup.setSelection(a);
}
for (int a = lvStickerGroup.getCount() - 1; a >= 0; a--) {
lvStickerGroup.setSelection(a);
}
}
});
I tried to programmatically scroll to bottom and back to top, same no luck, except programmatically scroll to the item position will not show in the first page when enter the fragment initially.
Besides, I tried to invalidate(), invalidateView() notifyDataSetChanged on the adapter, same problem occurs, is it possibly a ListView bug?
Nothing wrong with the code above, fully functional. I found the clue in Google ListView IO conference
https://www.youtube.com/watch?v=wDBM6wVEO70
ListView cannot wrap content, else will have bugs showing up. That why I experience such issue.

Wrong Loading Data when using Viewholder in BaseAdapter Android

I am using BaseAdapter for loading the data in gridview. When the data is loaded to the gridview, and the user tries to scroll, I used to get incorrect data. In order to fix that I used ViewHolder. That actually fixed the issue, however, when the users click any of the data in the gridview, instead of getting the correct id from the item, all the items are returning a similar id number.
public class ProductAdapter extends BaseAdapter {
// Context context;
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater = null;
ViewHolder holder;
int layoutResourceId;
Event event;
EventDBAdapter eventDb;
int id;
PersianCalendar sc;
String Today;
SharedPreferences Prefrences_test;
String date, userid;
String newText = "";
String test;
int status;
MoodsDBAdapter moodsDBAdapter;
Mood mood;
ArrayList<MoodsNote> arrayMoodsNote;
MoodsNoteDBAdapter moodsNoteDBAdapter;
MoodsNote moodsNote;
public ProductAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
// this.context = context;
eventDb = new EventDBAdapter(activity);
event = new Event();
moodsDBAdapter = new MoodsDBAdapter(activity);
mood = new Mood();
moodsNoteDBAdapter = new MoodsNoteDBAdapter(activity);
data = d;
// this.layoutResourceId = layoutResourceId;
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Prefrences_test = activity.getSharedPreferences("temp", 0);
date = Prefrences_test.getString("date", "");
userid = Prefrences_test.getString("userid", "");
sc = new PersianCalendar();
Today = date;
eventDb = new EventDBAdapter(activity.getApplicationContext());
event = eventDb.getName(Today);
try {
arrayMoodsNote = moodsNoteDBAdapter.getItems(event.getID());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
holder = null;
HashMap<String, String> song = new HashMap<String, String>();
song = data.get(position);
if (vi == null) {
vi = inflater.inflate(R.layout.note_mood_list_item, null);
holder = new ViewHolder();
holder.title = (TextView) vi.findViewById(R.id.mood_text);
holder.txt_id = (TextView) vi.findViewById(R.id.txt_id_mood);
holder.thumb_image = (ImageView) vi.findViewById(R.id.mood_img);
holder.linear = (LinearLayout) vi.findViewById(R.id.mood_layout);
vi.setTag(holder);
} else {
holder = (ViewHolder) vi.getTag();
}
holder.linear.setBackgroundResource(R.drawable.bg_mood);
//holder.txt_id.setText("");
String titles = song.get("name");
holder.title.setText(titles);
Resources res = activity.getResources();
int resourceId = res.getIdentifier(song.get("icon"), "drawable",
activity.getPackageName());
holder.thumb_image.setBackgroundResource(resourceId);
holder.txt_id.setText(song.get("id"));
try {
for (MoodsNote m : arrayMoodsNote) {
int moodd = m.getMOOD();
if (Integer.parseInt(holder.txt_id.getText().toString()) == moodd)
{
holder.linear.setBackgroundResource(R.drawable.bg_mood_on);
}
}
} catch (Exception e) {
// TODO: handle exception
}
holder.thumb_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Toast.makeText(activity, holder.txt_id.getText().toString(), 0).show();
status = 1;
event = new Event();
int tedad = eventDb.getDate(date);
if (tedad <= 0) {
event = new Event(userid, date);
eventDb.insert(event);
}
event = eventDb.getName(date);
moodsNote = new MoodsNote();
id = 0;
id = Integer.parseInt(holder.txt_id.getText().toString());
// id = rowItem.getID();
int tedadd = moodsNoteDBAdapter.getLastItemID(id);
if (tedadd <= 0)
{
moodsNote.setMOOD(id);
moodsNote.setEVENT(event.getID());
moodsNoteDBAdapter.insert(moodsNote);
holder.linear.setBackgroundResource(R.drawable.bg_mood_on);
}
else {
moodsNoteDBAdapter.deleteId(id);
holder.linear.setBackgroundResource(R.drawable.bg_mood);
}
}
});
return vi;
}
static class ViewHolder {
ImageView thumb_image;
TextView txt_id, title;
LinearLayout linear;
}

How to update the dynamic listView values in android

I am working on TCP socket, I receive some bunch of data for every sec and need to display it in ListView for that I am using a dynamic listView with custom array adapter.
My problem is, when I receive a new set of data from TCP socket, a new object is creating for listItem (findViewById), because of it when I scroll my listview, again it is moving to top when I am updating my listView.
When I consider only one set of data I did not find the above issue.
My code:
doAsynchronousTask = new TimerTask() {
#Override
public void run() {
finalizer = new Runnable() {
public void run() {
try {
new RetriveStock().execute(); // AsyncTask Executes for every 1 sec.
} catch (Exception e) {
// TODO: handle exception
}
}
}
};
handler.post(finalizer);
}
};
timer.schedule(doAsynchronousTask, 0, 1000); // execute in every 1000
// AsyncTask
public class RetriveStock extends AsyncTask<Void, Void, ArrayList<User>> {
#Override
protected ArrayList<User> doInBackground(Void... params) {
message += client.clientReceive(1); // Receive data from socket and put into message (string global variable).
printJson(); // Here I receive data from JSON and put into object
adb = new RSSListAdaptor(DefaultMarketWatch.this,
R.layout.rssitemview, list); // "list" is a global listAdapter.
return null;
}
#Override
protected void onCancelled() {
super.onCancelled();
}
protected void onPostExecute(ArrayList<User> result) {
lv.setAdapter(adb);
adb.notifyDataSetChanged();
super.onPostExecute(result);
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
// printJson()
public void printJson() {
String str = "";
/* SOME CODE HERE
FORMATING "message" (STRING VARIABLE) TO A PERFECT JSONARRAY FORMATE, AND PUT INTO VARIABLE "str" */
str = "[" + str + "]";
try {
JSONArray jsonArray = new JSONArray(str);
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject json = jsonArray.getJSONObject(i);
User obj = new User();
// MY CODE, EITHER ADDING NEW OBJECT OR UPDATING THE EXISTING USER OBJECT.
list.add(obj);
} catch (JSONException e1) {
e1.printStackTrace();
}
}
// My Custom ArrayAdapter.
public class RSSListAdaptor extends ArrayAdapter<User> {
private List<User> objects = null;
public RSSListAdaptor(Context context, int textviewid,
List<User> objects) {
super(context, textviewid, objects);
this.objects = objects;
}
#Override
public int getCount() {
return ((null != objects) ? objects.size() : 0);
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(final int position, View convertView,
ViewGroup parent) {
View view = convertView;
if (null == view) {
LayoutInflater vi = (LayoutInflater) DefaultMarketWatch.this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.rssitemview, null);
}
try {
User u = objects.get(position);
if (null != u) {
TextView title_list = (TextView) view.findViewById(R.id.symbol);
TextView ltp_list = (TextView) view.findViewById(R.id.ltp);
TextView high_list = (TextView) view.findViewById(R.id.high);
TextView low_list = (TextView) view.findViewById(R.id.low);
TextView persend_list = (TextView) view.findViewById(R.id.persent);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) title_list
.getLayoutParams();
params.setMargins(0, 0, 25, 0);
title_list.setText("TITLE");
ltp_list.setText("LTP");
high_list.setText("HIGH");
low_list.setText("LOW");
persend_list.setText("PERSENTAGE");
}
} catch (IllegalStateException is) {
is.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return view;
}
}
Try this:
// save index and top position
int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
// update listview with new data
// restore
mList.setSelectionFromTop(index, top);
Or
// Save ListView state
Parcelable state = listView.onSaveInstanceState();
// Set new items
listView.setAdapter(adapter);
// Restore previous state (including selected item index and scroll position)
listView.onRestoreInstanceState(state);
Do not recreate the adapter in doInBackground and do not reset it in onPostExecute
Rather create an empty adapter in your constructor or somewhere sensible, and when data comes in, append that data to your adapter then call notifyDataSetChanged

ListView shows wrong placement of images taken from URL

My listview doesn't show exact placement of images on its individual custom adapters. I am trying to load the images using AsyncTask. Sometimes the images duplicates and I don't have any idea why. Here is my ArrayAdapter code:
public class NewsPromoAdapter extends ArrayAdapter<NewsPromosDTO> {
private final Context context;
List<NewsPromosDTO> npList;
LayoutInflater inflater;
Bitmap src;
public NewsPromoAdapter(Context context, List<NewsPromosDTO> npList) {
super(context, R.layout.news_and_promos, npList);
this.context = context;
this.npList = npList;
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public static class ViewHolder {
TextView nameText;
TextView date1Text;
ImageView imageView;
ProgressBar prg;
LoadImage loadImg;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.news_and_promos, parent,
false);
holder = new ViewHolder();
holder.nameText = (TextView) convertView
.findViewById(R.id.newspromo_name);
holder.date1Text = (TextView) convertView
.findViewById(R.id.newspromo_date);
holder.imageView = (ImageView) convertView
.findViewById(R.id.newspromo_imageView);
holder.prg = (ProgressBar) convertView
.findViewById(R.id.progressBar1);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
holder.loadImg.cancel(true);
}
if (!(npList.get(position).getName().equals(""))) {
holder.nameText.setVisibility(View.VISIBLE);
holder.nameText.setText(npList.get(position).getName());
} else {
holder.nameText.setVisibility(View.GONE);
}
if (!(npList.get(position).getDate().equals(""))) {
holder.date1Text.setVisibility(View.VISIBLE);
holder.date1Text.setText(npList.get(position).getDate());
} else {
holder.date1Text.setVisibility(View.GONE);
}
if (!(npList.get(position).getImageURL().equals(""))) {
holder.imageView.setVisibility(View.VISIBLE);
holder.loadImg = new LoadImage(holder.imageView, npList.get(
position).getImageURL(), holder);
holder.loadImg.execute();
} else {
holder.imageView.setVisibility(View.GONE);
holder.prg.setVisibility(View.GONE);
}
return convertView;
}
class LoadImage extends AsyncTask<Object, Void, Bitmap> {
ViewHolder viewH;
private ImageView imv;
private String url;
public LoadImage(ImageView imv, String imageURL, ViewHolder viewH) {
this.imv = imv;
this.url = imageURL;
this.viewH = viewH;
}
#Override
protected Bitmap doInBackground(Object... params) {
BitmapFromURL bmpURL = new BitmapFromURL();
src = bmpURL.getBitmapFromURL(url);
return src;
}
#Override
protected void onPostExecute(Bitmap result) {
// imv.setImageBitmap(result);
// viewH.prg.setVisibility(View.GONE);
viewH.prg.setVisibility(View.GONE);
imv.setImageBitmap(result);
}
}
}
Here is the Activity that handles the ADAPTER. I am implementing the Endless listview approach that some big sites uses. Like Facebook, Twitter, etc..New Items loaded into the listview when scrolling into the bottom. I am not sure if I did it well.
public class ListNewsPromoActivity extends Activity {
List<NewsPromosDTO> npList;
String url, user_email;
Bundle extras;
int user_points;
List<Integer> npIDs;
private ProgressDialog progressDialog;
BitmapFromURL bmpURL;
JSONArray users = null;
String TAG_ID = "id";
String TAG_NAME = "name";
String TAG_PHOTO = "photo";
String TAG_DATE = "date";
String TAG_DESC = "description";
ListView list;
NewsPromoAdapter newsAdapter;
boolean loadingMore = false;
private Runnable returnRes;
int itemsPerPage = 3;
int currentIndex = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.news_promo_listview);
list = (ListView) findViewById(R.id.mainView);
extras = getIntent().getExtras();
if (extras != null) {
user_points = extras.getInt("user_points");
user_email = extras.getString("user_email");
}
url = getString(R.string.app_url_news_promos);
npIDs = new ArrayList<Integer>();
npList = new ArrayList<NewsPromosDTO>();
View footerView = ((LayoutInflater) this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
R.layout.footer, null, false);
newsAdapter = new NewsPromoAdapter(ListNewsPromoActivity.this, npList);
list.addFooterView(footerView);
list.setAdapter(newsAdapter);
list.setOnScrollListener(new OnScrollListener() {
// useless here, skip!
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
// what is the bottom item that is visible
int lastInScreen = firstVisibleItem + visibleItemCount;
// is the bottom item visible & not loading more already ? Load
if ((lastInScreen == totalItemCount) && !(loadingMore)) {
Thread thread = new Thread(null, getRunnable());
thread.start();
}
}
});
// Runnable to load the items
// Since we cant update our UI from a thread this Runnable takes care of
// that!
returnRes = new Runnable() {
#Override
public void run() {
// Loop thru the new items and add them to the adapter
for (NewsPromosDTO np : npList) {
System.out.println(np.getName() + " andito ako!!");
newsAdapter.add(np);
}
newsAdapter.notifyDataSetChanged();
// Done loading more.
loadingMore = false;
}
};
}
protected class loadNewsPromo extends AsyncTask<Void, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected String doInBackground(Void... params) {
// Creating JSON Parser instance
loadingMore = true;
JSONParser jParser = new JSONParser();
JSONObject json;
if (jParser.checkServer(url)) {
try {
// Getting Array of UserNews
json = jParser.getJSONFromUrl(url);
users = json.getJSONArray(user_email);
// looping through All UserNews
for (int i = currentIndex; i < itemsPerPage; i++) {
if (itemsPerPage == i) {
// currentIndex--;
break;
} else {
JSONObject c = users.getJSONObject(i);
// Storing each json item in variable
NewsPromosDTO npDTO = new NewsPromosDTO();
npDTO.setImageURL(c.getString(TAG_PHOTO));
npDTO.setId(c.getInt(TAG_ID));
npDTO.setName(c.getString(TAG_NAME));
npDTO.setDate(c.getString(TAG_DATE));
npDTO.setDescription(c.getString(TAG_DESC));
npList.add(npDTO);
currentIndex++;
}
}
} catch (JSONException e) {
e.printStackTrace();
return null;
} finally {
}
}
}
return null;
}
#Override
protected void onPostExecute(String result) { //
// progressDialog.dismiss();
loadingMore = false;
list();
}
}
public void list() {
// add the footer before adding the adapter, else the footer will not
// load!
View footerView = ((LayoutInflater) this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(
R.layout.footer, null, false);
newsAdapter = new NewsPromoAdapter(ListNewsPromoActivity.this, npList);
list.addFooterView(footerView);
list.setAdapter(newsAdapter);
}
public Runnable getRunnable() {
Runnable loadMoreListItems = new Runnable() {
#Override
public void run() {
// Set flag so we cant load new items 2 at the same time
loadingMore = true;
// Reset the array that holds the new items
// Simulate a delay, delete this on a production environment!
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
// Get 15 new listitems
JSONParser jParser = new JSONParser();
JSONObject json;
npList = new ArrayList<NewsPromosDTO>();
if (jParser.checkServer(url)) {
try {
// Getting Array of Contacts
json = jParser.getJSONFromUrl(url);
users = json.getJSONArray(user_email);
// looping through All Contacts
// if (itemsPerPage > users.length() - currentIndex) {
// itemsPerPage = users.length();
// }
npList = new ArrayList<NewsPromosDTO>();
System.out.println(users.length() + " Laman ng users");
int counter = 0;
for (int i = currentIndex; i < users.length(); i++) {
if (itemsPerPage == counter) {
break;
} else {
JSONObject c = users.getJSONObject(i);
// Storing each json item in variable
NewsPromosDTO npDTO = new NewsPromosDTO();
npDTO.setImageURL(c.getString(TAG_PHOTO));
npDTO.setId(c.getInt(TAG_ID));
npDTO.setName(c.getString(TAG_NAME));
npDTO.setDate(c.getString(TAG_DATE));
npDTO.setDescription(c.getString(TAG_DESC));
npList.add(npDTO);
currentIndex++;
}
counter++;
}
} catch (JSONException e) {
e.printStackTrace();
} finally {
}
}
// Done! now continue on the UI thread
runOnUiThread(returnRes);
}
};
return loadMoreListItems;
}
}

Categories

Resources