I have and android app that works on android 4.0 great, but it crashes on android 4.3 and 4.4. I get this from the logCat
01-11 14:40:27.669: E/ACRA(25835): ACRA caught a IllegalStateException exception for quran. Building report.
01-11 14:40:27.789: E/AndroidRuntime(25835): java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(2131099688, class android.widget.ListView) with Adapter(class quran.functions.PlaylistAdapter)]
Here is my code:
public class Playlist extends FragmentActivity {
private ListView list;
private Button manager, downloadAll;
private TextView reciter;
public static PlaylistAdapter adapter;
private ArrayList<Songs> songs;
private int RECITER_ID;
private String url, title, label;
private SlidingMenu slidingMenu;
private DatabaseHelper db;
private ImageView nowPlaying, back;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.playlist);
initWidgets();
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
Intent intent = new Intent(Playlist.this, PlayerFinal.class);
intent.putExtra("songs", songs);
if (getIntent().getIntExtra("duaa", -1) == 115)
intent.putExtra("lang", 115);
intent.putExtra("position", position);
intent.putExtra("fromClass", this.getClass() + "");
// intent.putExtra("mp3link", mp3link);
startActivity(intent);
}
});
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
XmlMapParser m = new XmlMapParser(Playlist.this, RECITER_ID);
HashMap<String, ArrayList<String>> map = m.convert();
map.keySet();
label = map.get("RecitorLabel").get(0);
title = map.get("Title").get(0);
url = map.get("Link").get(0);
back = (ImageView) findViewById(R.id.playlist_back);
back.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
finish();
}
});
db.openDB();
for (int i = 1; i < map.get("Link").size(); i++) {
if (db.isDownloaded(i, title, RECITER_ID)) {
songs.add(new Songs(i, map.get("Title").get(i),
Environment.getExternalStorageDirectory()
.getPath()
+ "/"
+ getString(R.string.app_name)
+ "/"
+ title
+ "/"
+ map.get("Title").get(i)
+ ".mp3", title, true, RECITER_ID,
false));
} else
songs.add(new Songs(i, map.get("Title").get(i), url
+ label + "/"
+ new DecimalFormat("000").format(i) + ".mp3",
title, false, RECITER_ID, false));
}
db.closeDB();
// Log.v("--",m.convert().get("Link").get(1));
// [RecitorLabel, Title, Link] THIS ARE THE KEYS m
// Log.v("--", map.get("RecitorLabel").get(0));
// Log.v("--", map.get("Link").get(1));
return null;
}
protected void onPostExecute(Void result) {
adapter = new PlaylistAdapter(Playlist.this, songs);
list.setAdapter(adapter);
reciter.setText(songs.get(0).getRecitorName());
};
}.execute();
}
#Override
public void onBackPressed() {
if (slidingMenu.isMenuShowing()) {
slidingMenu.toggle();
} else {
super.onBackPressed();
}
}
#Override
protected void onResume() {
super.onResume();
try {
if (Tplayer.getInstance().isPlaying()) {
adapter = new PlaylistAdapter(this, songs);
list.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU) {
this.slidingMenu.toggle();
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
this.slidingMenu.toggle();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void initWidgets() {
db = new DatabaseHelper(this);
manager = (Button) findViewById(R.id.playlist_download_manager);
manager.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Playlist.this, DownloadManager.class);
startActivity(intent);
}
});
reciter = (TextView) findViewById(R.id.playlist_reciter_name_top);
list = (ListView) findViewById(R.id.playlist_list);
downloadAll = (Button) findViewById(R.id.playlist_download_all);
manager = (Button) findViewById(R.id.playlist_download_manager);
songs = new ArrayList<Songs>();
RECITER_ID = getIntent().getIntExtra("filename", -1);
// downloadAll.setOnClickListener(new OnClickListener() {
//
// #Override
// public void onClick(View v) {
// new DownloadAll(Playlist.this, songs);
// db.openDB();
// for (int i = 0; i < songs.size(); i++) {
// db.addDownloaded(songs.get(i).getNumber(), songs.get(i)
// .getLink(), 0, songs.get(i).getRecitorID(), "",
// songs.get(i).getTitle());
// }
// db.closeDB();
// }
// });
nowPlaying = (ImageView) findViewById(R.id.playlist_now_playing);
nowPlaying.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Tplayer tplayer = Tplayer.getInstance();
if (tplayer.isPlaying()) {
Intent intent = new Intent(Playlist.this, PlayerFinal.class);
if (tplayer.isPlaying())
intent.putExtra("songs", tplayer.getSongs());
else
intent.putExtra("songs", songs);
if (tplayer.getSongs().size() == 14)
intent.putExtra("lang", 115);
intent.putExtra("position", tplayer.getPosition());
startActivity(intent);
}
}
});
// Jeremy Feinstein slidinglistadapter line 94
slidingMenu = new SlidingMenu(this);
slidingMenu.setMode(SlidingMenu.LEFT);
slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
slidingMenu.setShadowWidthRes(R.dimen.slidingmenu_shadow_width);
slidingMenu.setShadowDrawable(R.drawable.slidingmenu_shadow);
slidingMenu.setBehindOffsetRes(R.dimen.slidingmenu_offset);
slidingMenu.setFadeDegree(0.35f);
slidingMenu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);
slidingMenu.setMenu(R.layout.slidingmenu);
}
}
and my playlist adapter class:
public class PlaylistAdapter extends BaseAdapter {
private Activity activity;
private static LayoutInflater inflater = null;
private ArrayList<Songs> data;
private DatabaseHelper db;
private SharedPreferences prefs;
int playpos;
int recitorID;
public PlaylistAdapter(Activity a, ArrayList<Songs> songs) {
activity = a;
data = songs;
db = new DatabaseHelper(a);
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
prefs = activity.getSharedPreferences("quantic.Quran",
Context.MODE_PRIVATE);
recitorID = prefs.getInt("recID", -1);
playpos = prefs.getInt("posPlaying", -1);
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View convertView,
final ViewGroup parent) {
View vi = convertView;
if (convertView == null)
vi = inflater.inflate(R.layout.song_item, parent, false);
ImageView download = (ImageView) vi
.findViewById(R.id.playlist_item_download);
db.openDB();
if (db.isDownloaded(data.get(position).getNumber(), data.get(position)
.getRecitorName(), data.get(position).getRecitorID()))
download.setImageResource(R.drawable.download_yes);
else {
download.setImageResource(R.drawable.download_no);
download.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
new DownloadFileFromURL(activity, data.get(position)
.getRecitorName(), data.get(position).getTitle(),
data.get(position).getLink(), data.get(position)
.getNumber(), data.get(position)
.getRecitorID()).execute();
if (!db.isDBOpen())
db.openDB();
db.addDownloaded(data.get(position).getNumber(),
data.get(position).getLink(), 0, data.get(position)
.getRecitorID(), "", data.get(position)
.getTitle());
Toast.makeText(activity,
"Downloading " + data.get(position).getTitle(),
Toast.LENGTH_SHORT).show();
}
});
}
db.closeDB();
TextView number = (TextView) vi.findViewById(R.id.playlist_item_num);
TextView reciterName = (TextView) vi
.findViewById(R.id.playlist_item_reciterName);
reciterName.setText(data.get(position).getRecitorName());
if (activity.getClass() == Playlist.class) {
reciterName.setVisibility(View.GONE);
}
TextView title = (TextView) vi.findViewById(R.id.playlist_item_reciter);
title.setText(data.get(position).getTitle());
number.setText((position + 1) + "");
ImageView eq = (ImageView) vi.findViewById(R.id.playlist_item_equlizer);
if (Tplayer.getInstance().isPlaying())
if (Tplayer.getInstance().getPosition() == position
&& data.get(position).getRecitorID() == Tplayer
.getInstance().getSong().getRecitorID()) {
eq.setVisibility(View.VISIBLE);
Ion.with(eq).load("http://darkodev.info/quran/dots.gif");
} else {
eq.setVisibility(View.GONE);
}
return vi;
}
}
Very old question, but no answer. I'm sure you have found a fix by now, but anyway.
You're changing the songs list object in background, and if Android decides to redraw your list (user scrolls your list), effectively accessing the songs list object, it may have changed and cause this exception to be thrown.
You need to use a temporary songs list and create a new adapter with it to update your list, thus not changing the current adapter list until you set a new adapter from the main UI thread.
Related
I have listview All the values are delete and update properly but only the last value is not delete in the listview.
Added a full fragment code. Take a look
For example
If I have three values in the listview If I delete 1 and 2 its removing and listview refresh properly but the last one is not refreshed in the listview
private SwipeMenuListView mylistview;
String userid;
private EditText txtsearch;
private ArrayList<JobItem> jobitems;
private JobListAdapter adapter;
SwipeMenuCreator creator;
ImageLoader imageLoader;
DisplayImageOptions options;
public Fragment_Employer_MyJobList() {
}
public static float dp2px(Context context, int dipValue) {
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, metrics);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.layoutjoblist, container, false);
imageLoader = ImageLoader.getInstance();
options = new DisplayImageOptions.Builder().cacheInMemory(true)
.displayer(new RoundedBitmapDisplayer(1000))
.cacheOnDisc(true).resetViewBeforeLoading(true)
.showImageForEmptyUri(R.drawable.img_app_icon)
.showImageOnFail(R.drawable.img_app_icon)
.showImageOnLoading(R.drawable.img_app_icon).build();
mylistview = (SwipeMenuListView) rootView.findViewById(R.id.mylistview);
creator = new SwipeMenuCreator() {
#Override
public void create(SwipeMenu menu) {
// create "open" item
SwipeMenuItem openItem = new SwipeMenuItem(
getActivity());
// set item background
openItem.setBackground(new ColorDrawable(Color.rgb(0xC9, 0xC9,
0xCE)));
// set item width
openItem.setWidth((int) dp2px(getActivity(), 90));
// set item title
openItem.setTitle("DELETE");
// set item title fontsize
openItem.setTitleSize(18);
// set item title font color
openItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(openItem);
}
};
txtsearch = (EditText) rootView.findViewById(R.id.txtsearch);
txtsearch.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable theWatchedText) {
String text = txtsearch.getText().toString().toLowerCase(Locale.getDefault());
if (adapter != null)
adapter.filter(text);
}
});
return rootView;
}
SharedPreferences settings;
#Override
public void onResume() {
super.onResume();
jobitems = new ArrayList<JobItem>();
jobitems.clear();
adapter.notifyDataSetChanged();
settings = getActivity().getSharedPreferences(AppUtils.PREFS_NAME, Context.MODE_PRIVATE);
userid = settings.getString("userid", "");
AuthController.getStaticInstance().
employer_joblist(getActivity(), userid, APIConstants
.POST, new AuthControllerInterface.AuthControllerCallBack()
{
#Override
public void onSuccess(String message) {
Log.e("==response==>", "==response==>" + message);
try {
JSONArray mainarray = new JSONArray(message);
for (int i = 0; i < mainarray.length(); i++) {
JSONObject json_job = mainarray.getJSONObject(i);
JobItem item = new JobItem();
item.Id = json_job.getString("ID");
item.EMPID = json_job.getString("EMPID");
item.TITLE = json_job.getString("TITLE");
item.DESC = json_job.getString("DESC");
item.CID = json_job.getString("CID");
item.PRICE = json_job.getString("PRICE");
item.LOCAT = json_job.getString("LOCAT");
item.ADATE = json_job.getString("ADATE");
item.FOLLOW = json_job.getString("FOLLOW");
JSONArray array = json_job.getJSONArray("IMAGES");
if (array.length() > 0) {
if (!array.isNull(0))
item.IMG1 = array.getString(0);
if (!array.isNull(1))
item.IMG2 = array.getString(1);
if (!array.isNull(2))
item.IMG3 = array.getString(2);
if (!array.isNull(3))
item.IMG4 = array.getString(3);
if (!array.isNull(4))
item.IMG5 = array.getString(4);
}
jobitems.add(item);
}
adapter = new JobListAdapter(getActivity(), jobitems);
mylistview.setAdapter(adapter);
mylistview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
JobItem item = jobitems.get(position);
Intent intent = new Intent(getActivity(), Activity_Emp_jobdetail.class);
Bundle bundle = new Bundle();
bundle.putSerializable("jobitem", item);
intent.putExtras(bundle);
startActivity(intent);
}
});
mylistview.setMenuCreator(creator);
mylistview.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
switch (index) {
case 0:
// unfollow
userid = settings.getString("userid", "");
AuthController.getStaticInstance().employer_delete_job(getActivity(), userid, jobitems.get(position).Id, APIConstants.POST, new AuthControllerInterface.AuthControllerCallBack() {
#Override
public void onSuccess(String message) {
Log.e("==response==>", "==response==>" + message);
try {
JSONObject obj = new JSONObject(message);
Toast.makeText(getActivity(), obj.getString("ERROR") + "", Toast.LENGTH_LONG).show();
// onResume();
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getActivity(), message + "", Toast.LENGTH_LONG).show();
// onResume();
}
//setup
onResume();
}
#Override
public void onFailed(String error) {
Log.e("==error==>", "==error==>" + error);
}
}, Fragment_Employer_MyJobList.this);
break;
}
// false : close the menu; true : not close the menu
return false;
}
});
} catch (JSONException e) {
e.printStackTrace();
try {
JSONObject obj = new JSONObject(message);
Toast.makeText(getActivity(), obj.getString("ERROR") + "", Toast.LENGTH_LONG).show();
} catch (JSONException e1) {
e1.printStackTrace();
Toast.makeText(getActivity(), message + "", Toast.LENGTH_LONG).show();
}
}
}
#Override
public void onFailed(String error) {
Log.e("==error==>", "==error==>" + error);
}
}, Fragment_Employer_MyJobList.this);
}
#Override
public void showLoading() {
AppUtils.showProgress(getActivity(), "Please wait...");
// onResume();
}
#Override
public void stopLoading() {
AppUtils.dismissProgress();
// onResume();
}
public class OnItemClickListner implements View.OnClickListener {
int mposition;
JobItem item;
public OnItemClickListner(int position, JobItem item) {
this.mposition = position;
this.item = item;
}
#Override
public void onClick(View v) {
Intent intent = new Intent(getActivity(), Activity_Emp_jobdetail.class);
Bundle bundle = new Bundle();
bundle.putSerializable("jobitem", item);
intent.putExtras(bundle);
startActivity(intent);
}
}
private class JobListAdapter extends BaseAdapter {
LayoutInflater _inflater;
private List<JobItem> worldpopulationlist = null;
private ArrayList<JobItem> arraylist;
public JobListAdapter(Context context, List<JobItem> worldpopulationlist) {
_inflater = LayoutInflater.from(context);
this.worldpopulationlist = worldpopulationlist;
this.arraylist = new ArrayList<JobItem>();
this.arraylist.addAll(worldpopulationlist);
}
public int getCount() {
// TODO Auto-generated method stub
return worldpopulationlist.size();
}
public JobItem getItem(int position) {
// TODO Auto-generated method stub
return worldpopulationlist.get(position);
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder _holder;
if (convertView == null) {
convertView = _inflater.inflate(R.layout.layout_job_row, null);
_holder = new ViewHolder();
_holder.txtjobtitle = (TextView) convertView
.findViewById(R.id.txtjobtitle);
_holder.txtjobbudget = (TextView) convertView
.findViewById(R.id.txtjobbudget);
_holder.txtjobdesc = (TextView) convertView
.findViewById(R.id.txtjobdesc);
_holder.imageviewjob = (ImageView) convertView
.findViewById(R.id.imageviewjob);
_holder.txtlocation = (TextView) convertView
.findViewById(R.id.txtlocation);
convertView.setTag(_holder);
} else {
_holder = (ViewHolder) convertView.getTag();
}
_holder.txtjobtitle.setText(worldpopulationlist.get(position).TITLE.trim());
_holder.txtjobbudget.setText(worldpopulationlist.get(position).PRICE.trim());
_holder.txtjobdesc.setVisibility(View.VISIBLE);
_holder.txtjobbudget.setVisibility(View.GONE);
_holder.txtjobdesc.setText(worldpopulationlist.get(position).DESC);
imageLoader.displayImage(worldpopulationlist.get(position).IMG1, _holder.imageviewjob, options);
_holder.txtlocation.setText(worldpopulationlist.get(position).LOCAT.trim());
//convertView.setOnClickListener(new OnItemClickListner(position, worldpopulationlist.get(position)));
return convertView;
}
private class ViewHolder {
ImageView imageviewjob;
TextView txtjobtitle, txtjobdesc;
TextView txtlocation, txtjobbudget;
}
// Filter Class
public void filter(String charText) {
charText = charText.toLowerCase(Locale.getDefault());
worldpopulationlist.clear();
if (charText.length() == 0) {
worldpopulationlist.addAll(arraylist);
} else {
for (JobItem wp : arraylist) {
if (wp.TITLE.toLowerCase(Locale.getDefault())
.contains(charText)) {
worldpopulationlist.add(wp);
}
}
}
notifyDataSetChanged();
}
}
}
you have to tell your ListView that something changed in it's former List by calling notifyDataSetChanged() method of your adapter
Also you should not create a new instance of ArrayList, but only clear the old instance. Don't forget to check for null before clearing.
try calling the adapter again with a null like.
setListAdapter()
I would like to pass the selected item "id" from listview to popupMenu , the mainActivity:
public class ListChildrenActivity extends AppCompatActivity implements Config, PopupMenu.OnMenuItemClickListener {
private static final String TAG = "ListChildrenActivity";
ProgressDialog progressDialog;
Toolbar toolbar;
ChildrenAdapter adapter;
ListView listView;
int idConnexion, id;
private SwipeRefreshLayout refreshLayout;
Intent intent;
Child childObj;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_child);
toolbar = (Toolbar) findViewById(R.id.toolbar_actionbar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("Listes des enfants");
toolbar.setNavigationIcon(R.drawable.back);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getBaseContext(), MainMedecinActivity.class);
startActivity(intent);
}
});
refreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_layout);
refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
showChildren();
}
});
showChildren();
listView = (ListView) findViewById(R.id.listview);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> myAdapter, View view, int itemInt, long lng) {
//String selectedFromList =(String) (lv.getItemAtPosition(myItemInt));
//Toast.makeText(ListChildrenActivity.this, selectedFromList, Toast.LENGTH_SHORT).show();
//TextView v = (TextView)view.findViewById(R.id.tv);
//String itemId = v.getText().toString();
childObj = (Child) listView.getItemAtPosition(itemInt);
id = childObj.getIdEnfant();
Toast.makeText(ListChildrenActivity.this, ""+id, Toast.LENGTH_SHORT).show();
}
});
}
public void showMenu(View v) {
PopupMenu popup = new PopupMenu(this, v);
popup.setOnMenuItemClickListener(this);
popup.inflate(R.menu.poupup_menu);
popup.show();
}
private ArrayList<Child> generateData(String content) {
ArrayList<Child> children = new ArrayList<Child>();
JSONObject jObj = null;
JSONArray ja = null;
try {
ja = new JSONArray(content);
for (int i = 0; i < ja.length(); i++) {
jObj = ja.getJSONObject(i);
children.add(new Child(jObj.getInt("idEnfant"), jObj.getString("nomEnfant"), jObj.getString("prenomEnfant")));
}
} catch (JSONException e) {
e.printStackTrace();
}
return children;
}
public void showChildren() {
if (!validate()) {
failed();
return;
}
SharedPreferences prefs = getSharedPreferences("Info_Connexion", Context.MODE_PRIVATE);
idConnexion = prefs.getInt("idConnexion", 0);
progressDialog = new ProgressDialog(ListChildrenActivity.this);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("La liste des enfants ...");
progressDialog.show();
if (isOnline()) {
requestData(SERVER_URL + "enfant/read/", idConnexion);
} else {
Toast.makeText(ListChildrenActivity.this, "Eroor network", Toast.LENGTH_SHORT).show();
}
}
private void requestData(String url, int id) {
DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
RequestPackage p = new RequestPackage();
p.setMethod("POST");
p.setUri(url);
p.setParam("idMedecin", String.valueOf(id));
MessagesTask task = new MessagesTask();
task.execute(p);
}
protected boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
return netInfo != null && netInfo.isConnectedOrConnecting();
}
public void success(final int id, final ProgressDialog progressDialog, String content, SwipeRefreshLayout refreshLayout) {
// 1. pass context and data to the custom adapter
adapter = new ChildrenAdapter(this, generateData(content));
// 2. Get ListView from activity_main.xml
// 3. setListAdapter
listView.setAdapter(adapter);
if (id != 0) {
refreshLayout.setRefreshing(false);
progressDialog.dismiss();
} else {
refreshLayout.setRefreshing(false);
progressDialog.dismiss();
Toast.makeText(ListChildrenActivity.this, "Eroor server or input", Toast.LENGTH_SHORT).show();
}
}
public boolean validate() {
boolean valid = true;
return valid;
}
public void failed() {
Toast.makeText(getBaseContext(), "List Children failed", Toast.LENGTH_LONG).show();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public boolean onMenuItemClick(MenuItem item) {
TextView scoreView = (TextView) findViewById(R.id.score);
switch (item.getItemId()) {
case R.id.infos:
intent = new Intent(getBaseContext(), ChildInformationsActivity.class);
intent.putExtra("idEnfant", id );
startActivity(intent);
return true;
case R.id.signes_diagnostic:
intent = new Intent(getBaseContext(), ChildSignesDiagnosticActivity.class);
intent.putExtra("idEnfant", id);
startActivity(intent);
return true;
case R.id.bilan_bio:
intent = new Intent(getBaseContext(), ChildBilanBioActivity.class);
intent.putExtra("idEnfant", id);
startActivity(intent);
return true;
case R.id.traitement_medical:
intent = new Intent(getBaseContext(), ChildTraitementMedicalActivity.class);
intent.putExtra("idEnfant", id);
startActivity(intent);
return true;
case R.id.imagerie:
intent = new Intent(getBaseContext(), ChildImagerieActivity.class);
intent.putExtra("idEnfant", id);
startActivity(intent);
return true;
default:
return false;
}
}
private class MessagesTask extends AsyncTask<RequestPackage, String, String> {
#Override
protected String doInBackground(RequestPackage... params) {
String content = HttpManager.getData(params[0]);
return content;
}
#Override
protected void onPreExecute() {
System.out.println("onPreExecute");
}
#Override
protected void onPostExecute(String content) {
Log.i(TAG, "------------------------" + content);
success(idConnexion, progressDialog, content, refreshLayout);
}
}
}
enter image description here
class adapter:
public class ChildrenAdapter extends ArrayAdapter<Child> {
private final Context context;
private final ArrayList<Child> childrenArrayList;
public ChildrenAdapter(Context context, ArrayList<Child> childrenArrayList) {
super(context, R.layout.row_child, childrenArrayList);
this.context = context;
this.childrenArrayList = childrenArrayList;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// 1. Create inflater
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// 2. Get rowView from inflater
View rowChildView = inflater.inflate(R.layout.row_child, parent, false);
// 3. Get the two text view from the rowView
TextView nameView = (TextView) rowChildView.findViewById(R.id.name);
TextView dateView = (TextView) rowChildView.findViewById(R.id.date);
TextView scoreView = (TextView) rowChildView.findViewById(R.id.score);
// 4. Set the text for textView
//String text = childrenArrayList.get(position).getNomEnfant())+" "+childrenArrayList.get(position).getNomEnfant();
nameView.setText(childrenArrayList.get(position).getNomEnfant()+" "+childrenArrayList.get(position).getPrenomEnfant());
dateView.setText("22/12/2012");
scoreView.setText(String.valueOf(childrenArrayList.get(position).getIdEnfant()));
scoreView.setBackgroundResource(R.drawable.circular_textview);
// 5. retrn rowView
return rowChildView;
}
}
Whene i click to the row of listview i get the "id" but how i can pass it to the popupMenu.
The solution: it just add settag(position) to imageview in getview, then :
public void showMenu(View v) {
PopupMenu popup = new PopupMenu(this, v);
popup.setOnMenuItemClickListener(this);
popup.inflate(R.menu.poupup_menu);
popup.show();
listView.performItemClick(v, (Integer) v.getTag(),listView.getItemIdAtPosition((Integer) v.getTag()));
}
You can use interface to communicate between them
In your adapter class, initialize
private OnItemSelectedListener mListener;
and add these methods
public void setOnItemClickLister(OnItemSelectedListener mListener) {
this.mListener = mListener;
}
//Creating an interface
public interface OnItemSelectedListener {
public void onItemSelected(String s);
}
in onClick function in adapter
use this
mListener.onItemSelected(id);
//id is your string
you can call it in MainActivity,
adapter.setOnItemClickLister(new OnItemSelectedListener() {
#Override
public void onItemSelected(String s) {
//you will get the string here, you can pass it as an argument in popup menu
}
});
On the adapter Side:
view.findViewById(R.id.menu_btn).setTag(id);
On the ListActivity Side:
public void showPopUp(View v){
currentId = v.getTag().toString();
PopupMenu popupMenu=new PopupMenu(this,v);
popupMenu.setOnMenuItemClickListener(ListActivity.this);
MenuInflater inflater=popupMenu.getMenuInflater();
inflater.inflate(R.menu.my_pop_up,popupMenu.getMenu());
popupMenu.show();
}
On XML side:
<ImageButton android:id="#+id/menu_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/ic_overflow"
android:layout_marginStart="10dp"
android:layout_marginEnd="20dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:onClick="showPopUp"/>
Note: onClick="showPopUp" is very critical here.
This should be helpful. Thank you.
Explanation:
I have a listview in my fragment. When I click one of the row of the listview it goes to another activity.In listview,I got the data from the adapter.
Inside the adapter view,I set the setOnClick().
Problem is when I click one of the row multiple time it is opening multiple activity.I want to restrict only one time click on the particular row over the listview item.
Here is my fragment where I get the listview and set the adapter-
public class HomeFragment extends Fragment{
public HomeFragment() {
}
public static String key_updated = "updated", key_description = "description", key_title = "title", key_link = "link", key_url = "url", key_name = "name", key_description_text = "description_text";
private static String url = "";
List<String> lst_key = null;
List<JSONObject> arr_completed = null;
List<String> lst_key2 = null;
List<JSONObject> lst_obj = null;
List<String> list_status = null;
ListView completed_listview;
int PagerLength = 0,exeption_flag=0;
View rootView;
private ViewPager pagerRecentMatches;
private ImageView imgOneSliderRecent;
private ImageView imgTwoSliderRecent;
private ImageView imgThreeSliderRecent;
private ImageView imgFourSliderRecent;
private ImageView imgFiveSliderRecent;
private ImageView imgSixSliderRecent;
private ImageView imgSevenSliderRecent;
private ImageView imgEightSliderRecent;
LinearLayout selector_dynamic;
LinearLayout Recent_header_layout;
FrameLayout adbar;
String access_token = "";
SharedPreferences sharedPreferences;
int current_pos=0,status_flag=0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(false);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_home, container, false);
findViews();
selector_dynamic = (LinearLayout) rootView.findViewById(R.id.selectors_dynamic);
adbar = (FrameLayout) rootView.findViewById(R.id.adbar);
new AddLoader(getContext()).LoadAds(adbar);
MainActivity activity = (MainActivity) getActivity();
access_token = activity.getMyData();
sharedPreferences = getContext().getSharedPreferences("HomePref", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
if (access_token == null || access_token=="") {
url = "https://api.litzscore.com/rest/v2/recent_matches/?access_token=" + sharedPreferences.getString("access_token", null) + "&card_type=summary_card";
} else {
editor.putString("access_token", access_token);
editor.commit();
url = "https://api.litzscore.com/rest/v2/recent_matches/?access_token=" + access_token + "&card_type=summary_card";
}
completed_listview = (ListView) rootView.findViewById(R.id.completed_listview);
Recent_header_layout = (LinearLayout) rootView.findViewById(R.id.Recent_header_layout);
Recent_header_layout.setVisibility(View.GONE);
if(!Utils.isNetworkConnected(getContext())){
dialog_popup();
}
else{
new TabJson().execute();
}
pagerRecentMatches.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return false;
}
});
return rootView;
}
#Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}
private void dialog_popup() {
final Dialog dialog = new Dialog(getContext());
DisplayMetrics metrics = getResources()
.getDisplayMetrics();
int screenWidth = (int) (metrics.widthPixels * 0.90);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.internet_alert_box);
dialog.getWindow().setLayout(screenWidth, WindowManager.LayoutParams.WRAP_CONTENT);
dialog.setCancelable(true);
Button btnNo = (Button) dialog.findViewById(R.id.btn_no);
Button btnYes = (Button) dialog.findViewById(R.id.btn_yes);
btnNo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
getActivity().finish();
}
});
dialog.show();
btnYes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!Utils.isNetworkConnected(getContext())){
dialog_popup();
}
else{
dialog.dismiss();
new TabJson().execute();
}
}
});
dialog.show();
}
public class TabJson extends AsyncTask<String, String, String> {
String jsonStr = "";
#Override
protected void onPreExecute() {
Utils.Pdialog(getContext());
}
#Override
protected String doInBackground(String... params) {
jsonStr = new CallAPI().GetResponseGetMethod(url);
exeption_flag=0;
status_flag = 0;
if (jsonStr != null) {
try {
if (jsonStr.equals("IO") || jsonStr.equals("MalFormed") || jsonStr.equals("NotResponse")) {
exeption_flag = 1;
} else {
JSONObject obj = new JSONObject(jsonStr);
if (obj.has("status") && !obj.isNull("status")) {
if (obj.getString("status").equals("false") || obj.getString("status").equals("403")) {
status_flag = 1;
} else {
JSONObject data = obj.getJSONObject("data");
JSONArray card = data.getJSONArray("cards");
PagerLength = 0;
lst_obj = new ArrayList<>();
list_status = new ArrayList<>();
lst_key = new ArrayList<>();
lst_key2 = new ArrayList<>();
arr_completed = new ArrayList<>();
for (int i = 0; i < card.length(); i++) {
JSONObject card_obj = card.getJSONObject(i);
if (card_obj.getString("status").equals("started")) {
PagerLength++;
lst_obj.add(card_obj);
list_status.add(card_obj.getString("status"));
lst_key.add(card_obj.getString("key"));
}
if (card_obj.getString("status").equals("notstarted")) {
PagerLength++;
lst_obj.add(card_obj);
list_status.add(card_obj.getString("status"));
lst_key.add(card_obj.getString("key"));
}
if (card_obj.getString("status").equals("completed")) {
arr_completed.add(card_obj);
lst_key2.add(card_obj.getString("key"));
}
}
}
}
}
}
catch(JSONException e){
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
Utils.Pdialog_dismiss();
if (status_flag == 1 || exeption_flag==1) {
dialog_popup();
} else {
Recent_header_layout.setVisibility(View.VISIBLE);
LiveAdapter adapterTabRecent = new LiveAdapter(getContext(), lst_obj, PagerLength, list_status, lst_key);
adapterTabRecent.notifyDataSetChanged();
pagerRecentMatches.setAdapter(adapterTabRecent);
pagerRecentMatches.setCurrentItem(current_pos);
ScheduleAdapter CmAdapter = new ScheduleAdapter(getContext(), arr_completed, lst_key2);
CmAdapter.notifyDataSetChanged();
completed_listview.setAdapter(CmAdapter);
}
}
}
private void findViews() {
pagerRecentMatches = (ViewPager) rootView
.findViewById(R.id.pager_recent_matches);
imgOneSliderRecent = (ImageView) rootView
.findViewById(R.id.img_one_slider_recent);
imgTwoSliderRecent = (ImageView) rootView
.findViewById(R.id.img_two_slider_recent);
imgThreeSliderRecent = (ImageView) rootView
.findViewById(R.id.img_three_slider_recent);
imgFourSliderRecent=(ImageView)rootView.findViewById(R.id.img_four_slider_recent);
imgFiveSliderRecent=(ImageView)rootView.findViewById(R.id.img_five_slider_recent);
imgSixSliderRecent=(ImageView)rootView.findViewById(R.id.img_six_slider_recent);
imgSevenSliderRecent = (ImageView) rootView.findViewById(R.id.img_seven_slider_recent);
imgEightSliderRecent = (ImageView) rootView.findViewById(R.id.img_eight_slider_recent);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
#Override
public void onDetach() {
super.onDetach();
}
}
After load the data from the server it passed to the onPost() i called an adapter which extends BaseAdpter
Here is my BaseAdapter
package adapter;
public class ScheduleAdapter extends BaseAdapter{
private Context context;
private List<JSONObject> arr_schedule;
private List<String> arr_matchKey;
private static LayoutInflater inflater;
int flag = 0;
String time="";
String status="";
String match_title = "";
String match_key="";
public ScheduleAdapter(Context context,List<JSONObject> arr_schedule,List<String> arr_matchKey){
this.context=context;
this.arr_schedule=arr_schedule;
this.arr_matchKey=arr_matchKey;
inflater=(LayoutInflater)this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return this.arr_schedule.size();
}
#Override
public Object getItem(int position) {
return this.arr_schedule.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
private class Holder{
TextView txt_one_country_name;
TextView txt_two_country_name;
TextView txt_venue;
TextView txtTimeGMT;
TextView txtDate;
TextView txtTimeIST;
ImageView team_one_flag_icon;
ImageView team_two_flag_icon;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
Holder holder=new Holder();
String[] parts;
String[] state_parts;
String[] match_parts;
Typeface tf=null;
String winner_team = "";
String final_Score="";
String now_bat_team="",team_name="";
String related_status="";
if(convertView==null) {
convertView = inflater.inflate(R.layout.recent_home_layout, null);
holder.txt_one_country_name = (TextView) convertView.findViewById(R.id.txt_one_country_name);
holder.txt_two_country_name = (TextView) convertView.findViewById(R.id.txt_two_country_name);
holder.txt_venue = (TextView) convertView.findViewById(R.id.venue);
holder.txtTimeIST = (TextView) convertView.findViewById(R.id.txt_timeist);
holder.txtTimeGMT = (TextView) convertView.findViewById(R.id.txt_timegmt);
holder.txtDate = (TextView) convertView.findViewById(R.id.txt_date);
holder.team_one_flag_icon = (ImageView) convertView.findViewById(R.id.team_one_flag_icon);
holder.team_two_flag_icon = (ImageView) convertView.findViewById(R.id.team_two_flag_icon);
tf = Typeface.createFromAsset(convertView.getResources().getAssets(), "Roboto-Regular.ttf");
holder.txt_one_country_name.setTypeface(tf);
holder.txt_two_country_name.setTypeface(tf);
holder.txt_venue.setTypeface(tf);
holder.txtTimeIST.setTypeface(tf);
holder.txtTimeGMT.setTypeface(tf);
holder.txtDate.setTypeface(tf);
convertView.setTag(holder);
}
else{
holder=(Holder)convertView.getTag();
}
try {
String overs="";
String wickets_now="";
String now_runs="";
String[] over_parts;
time = "";
JSONObject mainObj = this.arr_schedule.get(position);
status = mainObj.getString("status");
String name = mainObj.getString("short_name");
String state = mainObj.getString("venue");
String title = mainObj.getString("title");
related_status=mainObj.getString("related_name");
JSONObject start_date = mainObj.getJSONObject("start_date");
JSONObject teams=null;
JSONObject team_a=null;
JSONObject team_b=null;
String team_a_key="";
String team_b_key="";
time = start_date.getString("iso");
parts = name.split("vs");
match_parts = title.split("-");
state_parts = state.split(",");
int length = state_parts.length;
flag=0;
match_title="";
winner_team="";
if (!mainObj.isNull("msgs")) {
JSONObject msgs = mainObj.getJSONObject("msgs");
winner_team = "";
if (msgs.has("info")) {
winner_team = msgs.getString("info");
flag = 1;
}
}
match_title=name+" - "+match_parts[1];
JSONObject now=null;
if(mainObj.has("now") && !mainObj.isNull("now")) {
now = mainObj.getJSONObject("now");
if (now.has("batting_team")) {
now_bat_team = now.getString("batting_team");
}
if (now.has("runs")) {
if (now.getString("runs").equals("0")) {
now_runs = "0";
} else {
now_runs = now.getString("runs");
}
}
if (now.has("runs_str") && !now.isNull("runs_str")) {
if (now.getString("runs_str").equals("0")) {
overs = "0";
} else {
if(now.getString("runs_str").equals("null")){
overs="0";
}
else{
over_parts=now.getString("runs_str").split(" ");
overs=over_parts[2];
}
}
}
if (now.has("wicket")) {
if (now.getString("wicket").equals("0")) {
wickets_now = "0";
} else {
wickets_now = now.getString("wicket");
}
}
}
try {
if (!mainObj.isNull("teams") && mainObj.has("teams")) {
teams = mainObj.getJSONObject("teams");
team_a = teams.getJSONObject("a");
team_b = teams.getJSONObject("b");
team_a_key = team_a.getString("key");
team_b_key = team_b.getString("key");
JSONArray team_arr = teams.names();
JSONObject team_obj;
for (int a = 0; a < team_arr.length(); a++) {
if (now_bat_team.equals(team_arr.getString(a))) {
team_obj = teams.getJSONObject(team_arr.getString(a));
if (team_obj.has("short_name") && !team_obj.isNull("short_name")) {
team_name = team_obj.getString("short_name");
}
}
}
}
}
catch (NullPointerException e){
e.printStackTrace();
}
if(mainObj.has("status_overview") && !mainObj.isNull("status_overview")){
if(mainObj.getString("status_overview").equals("abandoned") || mainObj.getString("status_overview").equals("canceled")){
final_Score="";
}
else{
final_Score=team_name+" - "+now_runs+"/"+wickets_now+" ("+overs+" ovr)";
}
}
holder.txt_one_country_name.setText(parts[0]);
holder.txt_two_country_name.setText(parts[1]);
if(length==1){
holder.txtTimeGMT.setTextSize(TypedValue.COMPLEX_UNIT_SP, 13);
holder.txtTimeGMT.setText(state_parts[0]);
}
if(length==2){
holder.txtTimeGMT.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
holder.txtTimeGMT.setText(state_parts[0] + "," + state_parts[1]);
}
if(length==3){
holder.txtTimeGMT.setTextSize(TypedValue.COMPLEX_UNIT_SP,12);
holder.txtTimeGMT.setText(state_parts[1] + "," + state_parts[2]);
}
if(length==4){
holder.txtTimeGMT.setTextSize(TypedValue.COMPLEX_UNIT_SP,12);
holder.txtTimeGMT.setText(state_parts[2] + "," + state_parts[3]);
}
holder.txtDate.setText(final_Score);
holder.txtDate.setTypeface(tf, Typeface.BOLD);
holder.txtDate.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
holder.txtTimeIST.setText(winner_team);
holder.txt_venue.setText(related_status);
} catch (JSONException e) {
e.printStackTrace();
}
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
match_key = arr_matchKey.get(position);
MainActivity activity = (MainActivity) context;
GetValue gv = new GetValue(context);
gv.setFullUrl(match_key);
gv.setAccessToken(activity.getMyData());
gv.execute();
}
});
return convertView;
}
#Override
public boolean isEnabled(int position) {
return super.isEnabled(position);
}
}
This adapter set the listrow item into listview.
In ScheduleAdapter.java i set the onclick() on the convertView in which i called a GetValue class which is only implement a Asynctask to get the data and called and intent then it goes to an activity.
Means HomeFragment->ScheduleAdapter->GetValue->Scorecard
Here,
HomeFragment is fragment which have listview
ScheduleAdpter is an adapter which set data to listview which reside in homefragment
GetValue is class which implement some important task and it passed an intent and goes to an activity(It's work as a background)
ScoreCard is my activity which called after click on the row of the listview which reside in HomeFragment.
Please, help me to solve out this problem.
You can use a flag in Listview click - isListClicked, and set flag value as false in onPostexecute method of Aysnc task class -GetValue
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!isListClicked){
match_key = arr_matchKey.get(position);
MainActivity activity = (MainActivity) context;
GetValue gv = new GetValue(context);
gv.setFullUrl(match_key);
gv.setAccessToken(activity.getMyData());
gv.execute();
isListClicked = true;
}
}
});
If you want to prevent multiple activities being opened when the user spams with touches, add into your onClick event the removal of that onClickListener so that the listener won't exist after the first press.
Easy way is you can create a model class of your json object with those field you taken in holder class. And add one more boolean field isClickable with by default with true value.Now when user press a row for the first time you can set your model class field isClickable to false. Now second time when user press a row,you will get a position of row and you can check for isClickable. it will return false this time.
Model Class :
public class CountryInfoModel {
//other fields to parse json object
private boolean isClickable; //<- add one more extra field
public boolean isClickable() {
return isClickable;
}
public void setIsClickable(boolean isClickable) {
this.isClickable = isClickable;
}
}
listview click perform :
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//country_list is your list of model class List<CountryInfo>
if(country_list.get(position).isClickable())
{
//Perform your logic
country_list.get(position).setIsClickable(false);
}else{
//Do nothing : 2nd time click
}
}
});
Try creating your custom click listener for your listview and use it. In this way
public abstract class OnListItemClickListener implements OnItemClickListener {
private static final long MIN_CLICK_INTERVAL=600;
private long mLastClickTime;
public abstract void onListItemSingleClick(View parent, View view, int position, long id);
public OnListItemClickListener() {
// TODO Auto-generated constructor stub
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO Auto-generated method stub
long currentClickTime=SystemClock.uptimeMillis();
long elapsedTime=currentClickTime-mLastClickTime;
mLastClickTime=currentClickTime;
if(elapsedTime<=MIN_CLICK_INTERVAL)
return;
onListItemSingleClick(parent, view, position, id);
}
}
Im using the cwac-endless EndlessAdapter with a custom ListViewAdapter. With an AsyncTask i get the data form he webserver in 2 phases.
1) i get all the id's of the elements
2) using the EndlessAdapter i want to load say 4 elements at a time (i get from the server 4 elements by their id)
The problem that im facing is that as i create my custom ListViewAdapter when i call the contructor of MyEndlessAdapter which creates the list of items with the first bach of items. when i load the next batch of elements my custom ListViewAdapter it gets the correct items from the server but i recycles the getView(graphic/visual stuff). What am i doing wrong!
I think a possible solution bwould be to use the add method of the CustomListView but i dont know how to call it from the CompraFragment class.
How do i solve this problem?
Thanks
ListViewAdapter code:
public class ListViewAdapter extends ArrayAdapter<Item> {
private LayoutInflater inflater = null;
private final String TAG = "ListViewAdapter";
public Context context;
public int layoutResourceId;
public ArrayList<Item> items;
public ListViewAdapter(Context context, int listviewItemRow, ArrayList<Item> items) {
// TODO Auto-generated constructor stub
super(context, listviewItemRow);
this.context = context;
this.items = items;
}
public ListViewAdapter(Context context, int listviewItemRow) {
super(context, listviewItemRow);
this.context = context;
}
#Override
public void add(Item object) {
Log.i(TAG, "---ADD---");
items.add(object);
//super.add(object);
}
#Override
public void clear() {
super.clear();
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
#Override
public void remove(Item object) {
super.remove(object);
}
#Override
public int getCount() {
return items.size();
}
public Item getItem(Item position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
Item item = items.get(position);
Log.w(TAG, "view of Item " + item.getId() + " at position " + position);
ItemView view;
if (convertView == null) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = (ItemView) inflater.inflate(R.layout.listview_item_row, null);
view.checkFollowing(item, this, 3);
view.setTag(Long.toString(item.getId()));
Log.e(TAG, "CREATED ITEM " + item.getId() + " at position " + position);
} else {
view = (ItemView) convertView;
Log.i(TAG, "RECYCLED ITEM " + item.getId() + " at position " + position);
}
view.setOnClickListener(new OnItemClickListener(position));
view.showItems(item);
return view;
}
private class OnItemClickListener implements OnClickListener {
private int mPosition;
private OnItemClickListener(int position){
mPosition = position;
}
#Override
public void onClick(View v) {
Toast.makeText(context, "Message " + Integer.toString(mPosition), Toast.LENGTH_SHORT).show();
Intent intent = new Intent(context, DettagliActivity.class);
Bundle bundle = new Bundle();
bundle.putInt("id", mPosition);
intent.putExtras(bundle);
context.startActivity(intent);
}
}
}
CompraFragment code:
public class CompraFragment extends ListFragment {
private static final String TAG = "CompraFragment";
public ListView listView;
public MyEndlessAdapter adapter = null;
public ListViewAdapter mListViewAdapter;
private DownloadTask mDownloadTask = null;
public ArrayList<Item> items;
public ArrayList<Long> ids;
public Bitmap icon;
public int currentItemId = 0;
public String category = "";
public String latitude = "";
public String longitude = "";
public String radius = "";
public String keywords = "";
public String order = "";
public String state = "2";
//numero di elementi caricabili sulla wall all volta
public final int BATCH_SIZE = 4;
public ProgressDialog progressDialog;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
progressDialog = new ProgressDialog(this.getActivity());
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar actions click
switch (item.getItemId()) {
case R.id.action_aggiorna:
items = new ArrayList<Item>();
ids = new ArrayList<Long>();
mDownloadTask = new DownloadTask();
mDownloadTask.execute();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO Auto-generated method stub
inflater.inflate(R.menu.compra, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i(TAG, "onCreateView");
Bundle extras = getActivity().getIntent().getExtras();
if (extras != null){
category = (String) extras.get("category");
latitude = (String) extras.get("latitude");
longitude = (String) extras.get("radius");
radius = (String) extras.get("radius");
keywords = (String) extras.get("keywords");
order = (String) extras.get("order");
state = (String) extras.get("state");
}
View rootView = inflater.inflate(R.layout.fragment_compra, container, false);
// now you must initialize your list view
listView = (ListView) rootView.findViewById(android.R.id.list);
mDownloadTask = new DownloadTask();
mDownloadTask.execute();
return rootView;
}
/**
* Represents an asynchronous task used to download
* information from the webserver and display the results
*/
public class DownloadTask extends AsyncTask<Integer, Void, Boolean> {
#Override
protected Boolean doInBackground(Integer... params) {
ids = new ArrayList<Long>();
ids = MVPFunctions.getInstance().search(category, latitude, longitude, radius, keywords, order, state);
if (ids.isEmpty()){
return false;
} else {
Log.i(TAG, "ids size = " + ids.size());
}
return true;
}
#Override
protected void onPreExecute(){
/*
* This is executed on UI thread before doInBackground(). It is
* the perfect place to show the progress dialog.
*/
//progressDialog = ProgressDialog.show(getActivity(), "", "Downloading Content...");
progressDialog.setMessage("Downloading Content...");
progressDialog.show();
}
#Override
protected void onPostExecute(final Boolean success) {
mDownloadTask = null;
if (!success){
Log.i("onPostExecute", "items null");
Toast.makeText(getActivity(), "Non ci sono elementi da caricare", Toast.LENGTH_LONG).show();
} else {
items = new ArrayList<Item>();
adapter = new MyEndlessAdapter(items);
adapter.setRunInBackground(false);
listView.setAdapter(adapter);
}
}
#Override
protected void onCancelled() {
mDownloadTask = null;
}
}
class MyEndlessAdapter extends EndlessAdapter implements IItemsReadyListener {
private RotateAnimation rotate = null;
MyEndlessAdapter(ArrayList<Item> list) {
super(new ListViewAdapter(getActivity(),R.layout.listview_item_row, list));
rotate = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotate.setDuration(600);
rotate.setRepeatMode(Animation.RESTART);
rotate.setRepeatCount(Animation.INFINITE);
Log.i(TAG, "CONSTRUCTER CALLED");
}
#Override
protected View getPendingView(ViewGroup parent) {
View row = getActivity().getLayoutInflater().inflate(R.layout.listview_item_row, null);
View child;
child = row.findViewById(R.id.relativeLayout);
child.setVisibility(View.GONE);
child = row.findViewById(R.id.throbber);
child.setVisibility(View.VISIBLE);
child.startAnimation(rotate);
return (row);
}
#Override
protected boolean cacheInBackground() throws Exception {
//Log.i(TAG, "cacheInBackground - items.size(): " + items.size());
new FetchDataTask(this, items.size()).execute();
if (items.size() < ids.size() ){
return true;
} else {
return false;
}
}
#Override
public void onItemsReady(ArrayList<Item> data) {
Log.e(TAG, "onItemsReady");
items.addAll(data);
// Tell the EndlessAdapter to remove it's pending view and call notifyDataSetChanged()
adapter.onDataReady();
progressDialog.dismiss();
}
#Override
protected void appendCachedData() {
// TODO Auto-generated method stub
}
}
interface IItemsReadyListener {
public void onItemsReady(ArrayList<Item> data);
}
class FetchDataTask extends AsyncTask<Void, Void, ArrayList<Item>> {
private static final String TAG = "FetchDataTask";
IItemsReadyListener listener;
//The point from where to start counting.
int startPoint;
protected FetchDataTask(IItemsReadyListener listener, int startPoint) {
this.listener = listener;
this.startPoint = startPoint;
}
#Override
protected ArrayList<Item> doInBackground(Void... params) {
ArrayList<Item> result = new ArrayList<Item>();
Item item;
for (int i = startPoint; ((i < ids.size()) && (i < startPoint + BATCH_SIZE)); i++) {
Log.i(TAG, "i = " + i);
item = MVPFunctions.getInstance().getItem(ids.get(i));
result.add(item);
}
return (result);
}
#Override
protected void onPostExecute(ArrayList<Item> result) {
listener.onItemsReady(result);
}
}
}
ItemView code:
public class ItemView extends LinearLayout {
public TextView prezzo;
public TextView scadenza;
public TextView followers;
public ImageView ic_thumbnail;
public ProgressBar hProgressBar;
public ToggleButton followButton;
public String nextFollowAction = "";
public ListViewAdapter lva;
public String mLogin;
public String mPassword;
public int statusCode;
public Item item;
public BackgroundTask mBackgroundTask = null;
public ItemView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
prezzo = (TextView)findViewById(R.id.tvPrezzo);
scadenza = (TextView)findViewById(R.id.tvScadenza);
followers = (TextView)findViewById(R.id.tvFollowers);
ic_thumbnail = (ImageView)findViewById(R.id.ic_thumbnail);
hProgressBar = (ProgressBar)findViewById(R.id.hProgressBar);
followButton = (ToggleButton)findViewById(R.id.btnFollow);
}
public void showItems(final Item item) {
prezzo.setText(item.getPrezzo());
ic_thumbnail.setImageBitmap(item.getIcon());
scadenza.setText(item.getScadenza());
followers.setText("Followers: " + item.getFollowers());
hProgressBar.setProgress(item.getCoefficient());
followButton.setTag(item.getId());
}
public void askForFollowing(String nextFollowAction, final Item item, final int statusCode){
//Log.e("status code fo item is", Integer.toString(statusCode) + " " + item.getId());
//Status code: 0 --> OK
if(statusCode == 0) {
//Log.i("statusCode == 0", "richiesta evasa correttamente");
changeFollowStatus(nextFollowAction, item);
}
// Status code 108 --> Oggetto giĆ seguito
else if ((statusCode == 108) && (nextFollowAction.contains("kCheckFollowAction"))) {
//Log.i("statusCode == 108", "gray");
nextFollowAction = "kUnfollowAction";
followButton.setEnabled(true);
followButton.setBackgroundResource(R.drawable.action_object_button_gray);
followButton.setText("seguito");
lva.notifyDataSetChanged();
followButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
view.setEnabled(false);
setFollowing("kUnfollowAction", item, (long) 2);
}
});
}
// Status code 122 --> Oggetto non ancora seguito
else if ((statusCode == 122) && (nextFollowAction.contains("kCheckFollowAction"))) {
//Log.i("statusCode == 122", "green");
nextFollowAction = "kFollowAction";
followButton.setEnabled(true);
followButton.setBackgroundResource(R.drawable.action_object_button_green);
followButton.setText("segui");
lva.notifyDataSetChanged();
followButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
view.setEnabled(false);
setFollowing("kFollowAction", item, (long) 1);
}
});
} else {
Log.e("error", "error non e ne 0 ne 108 ne 122");
Log.e("error", nextFollowAction);
Log.e("error", Long.toString(item.getId()));
Log.e("error", Integer.toString(statusCode));
}
}
public void changeFollowStatus(String nextFollowAction, Item item){
//Log.i("changeFollowStatus action", nextFollowAction);
if(nextFollowAction.contains("kFollowAction")) {
//Log.w("changeFollowStatus increase", "+1");
nextFollowAction = "kUnfollowAction";
followButton.setBackgroundResource(R.drawable.action_object_button_gray);
followButton.setText("seguito");
followButton.getTextOn();
increaseFollowers(item);
}
else if(nextFollowAction.contains("kUnfollowAction")){
//Log.w("changeFollowStatus decrease", "-1");
nextFollowAction = "kFollowAction";
followButton.setBackgroundResource(R.drawable.action_object_button_green);
followButton.setText("segui");
followButton.getTextOff();
decreaseFollowers(item);
}
}
public void increaseFollowers(Item item){
int updatedFollowers = Integer.parseInt(item.getFollowers()) + 1;
item.setFollowers(Integer.toString(updatedFollowers));
followers.setText("Followers: " + item.getFollowers());
}
public void decreaseFollowers(Item item){
int updatedFollowers = Integer.parseInt(item.getFollowers()) - 1;
item.setFollowers(Integer.toString(updatedFollowers));
followers.setText("Followers: " + item.getFollowers());
}
public void checkFollowing(Item item, ListViewAdapter listViewAdapter, long follow) {
this.lva = listViewAdapter;
mBackgroundTask = new BackgroundTask();
try {
int statusCode = mBackgroundTask.execute(item.getId(), follow).get();
askForFollowing("kCheckFollowAction", item, statusCode);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public void setFollowing(String nextFollowAction, Item item, Long follow){
mBackgroundTask = new BackgroundTask();
try {
int statusCode = mBackgroundTask.execute(item.getId(), follow).get();
/*
Log.i("setFollowing p1", Long.toString(follow));
Log.i("setFollowing p1", nextFollowAction);
Log.i("setFollowing p2", Long.toString(item.getId()));
Log.i("setFollowing p3", Integer.toString(statusCode));
*/
askForFollowing(nextFollowAction, item, statusCode);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Represents an asynchronous task used to download
* information from the webserver and display the results
*/
public class BackgroundTask extends AsyncTask<Long, Void, Integer> {
private int statusCode;
#Override
protected Integer doInBackground(Long... params) {
// TODO: attempt authentication against a network service.
statusCode = MVPFunctions.getInstance().followItem(mLogin, mPassword, params[0], params[1].intValue());
return statusCode;
}
#Override
protected void onPreExecute(){
/*
* This is executed on UI thread before doInBackground(). It is
* the perfect place to show the progress dialog.
*/
}
#Override
protected void onPostExecute(Integer result) {
mBackgroundTask = null;
//askForFollowing("kCheckFollowAction", item, statusCode);
//listViewAdapter.notifyDataSetChanged();
//result1 = listener.processFinish(result);
//setStatusCode(result);
//delegate.processFinish(result);
//ItemView
//Log.i("onPostExecute statusCode", Integer.toString(success) + " = " + Integer.toString(statusCode));
}
#Override
protected void onCancelled() {
mBackgroundTask = null;
}
}
}
When a view is recycled [i.e., passed to getView() as a non-null convertView], you need to update it to reflect the state of the current item. So, the 2 lines indicated below need to be moved after the if/then block.
public View getView(final int position, View convertView, ViewGroup parent) {
Item item = items.get(position);
Log.w(TAG, "view of Item " + item.getId() + " at position " + position);
ItemView view;
if (convertView == null) {
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = (ItemView) inflater.inflate(R.layout.listview_item_row, null);
Log.e(TAG, "CREATED ITEM " + item.getId() + " at position " + position);
} else {
view = (ItemView) convertView;
Log.i(TAG, "RECYCLED ITEM " + item.getId() + " at position " + position);
}
// ===> These 2 lines always need to be executed. <===
view.checkFollowing(item, this, 3);
view.setTag(Long.toString(item.getId()));
view.setOnClickListener(new OnItemClickListener(position));
view.showItems(item);
return view;
}
I have a bug that I think is due to the way that lists reuse objects. I have a list of download buttons that get a progress readout when downloading. The update code is in a background thread.
When I scroll the list, the buttons that are showing progress jump into other list elements. How can I stop this? It's difficult to visualize, so I made a video of it:
http://www.youtube.com/watch?v=EiT2YWb2Prs&feature=youtu.be
BTW, the video was made by my client, so disregard the "samsung bug" bit. I'm the developer...
Here is the code:
public class VideosActivity extends Activity {
ListView video_list;
CustomList2 adapter;
File storage_dir;
String s3_bucket = "xx";
String s3_dir = "android/vol1/"; //the directory after the boucket that the files are stored in (do not add first slash)
Handler handler = new Handler(); //'tunnel' through whci other threads communicate with main thread
ArrayList<String> arr_videos = new ArrayList<String>();
ArrayList<String> arr_sdcardvideos = new ArrayList<String>();
int images[] = {R.drawable.kr115,R.drawable.kr200,R.drawable.kr201,R.drawable.kr202,R.drawable.kr203,R.drawable.kr205,R.drawable.kr206,R.drawable.kr207,R.drawable.kr208,R.drawable.kr209,R.drawable.kr210,R.drawable.kr211,R.drawable.kr212,R.drawable.kr213,R.drawable.kr213,R.drawable.kr214,R.drawable.kr215,R.drawable.kr216,R.drawable.kr210,R.drawable.kr211,R.drawable.kr212,R.drawable.kr213};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
storage_dir = getApplicationContext().getExternalFilesDir(null); //private to app, removed with uninstall
adapter = new CustomList2(this, R.layout.customlist, arr_videos);
video_list = (ListView)findViewById(R.id.list);
video_list.setAdapter(adapter); //set adapter that specifies list contents
ensureStorageDirExists( storage_dir ); //make sure storage dir exists
set_sdcard_video_data(); //store vids arleady on card
set_video_data(); //store vid dat in array
if(!have_connection())
{
Toast.makeText(this, "No Internet connection", Toast.LENGTH_LONG).show();
return;
}
}
protected void ensureStorageDirExists( File dir )
{
if (!dir.exists())
{
dir.mkdirs();
}
}
public void set_sdcard_video_data()
{
arr_sdcardvideos.clear();
for(File f:storage_dir.listFiles())
{
arr_sdcardvideos.add( f.getName() );
}
}
public void set_video_data()
{
arr_videos.add("02Posture_and_Walk.m4v");
arr_videos.add("03Embrace_Connection_and_Musicality.m4v");
arr_videos.add("04Left_Turning_Check_Step.m4v");
arr_videos.add("05Basic_Right_Turn.m4v");
arr_videos.add("06Ocho_Cortado.m4v");
arr_videos.add("07Media_Vuelta.m4v");
arr_videos.add("08The_Cross.m4v");
arr_videos.add("09Front_Ochos.m4v");
arr_videos.add("10The_Cross_in_Cross_System.m4v");
arr_videos.add("11Back_Ochos.m4v");
arr_videos.add("12Molinete_Giro.m4v");
arr_videos.add("13Right_Turn.m4v");
arr_videos.add("14Combining_All_the_Elements_1.m4v");
arr_videos.add("15Combining_All_the_Elements_2.m4v");
arr_videos.add("16Combining_All_the_Elements_3.m4v");
arr_videos.add("17Combining_All_the_Elements_4.m4v");
arr_videos.add("18Combining_All_the_Elements_5.m4v");
arr_videos.add("19Combining_All_the_Elements_6.m4v");
arr_videos.add("20Demo_Using_All_the_Elements.m4v");
arr_videos.add("36Etiquette.m4v");
}
public SharedPreferences stored_vals()
{
return PreferenceManager.getDefaultSharedPreferences(this);
}
public boolean have_connection()
{
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if(cm.getActiveNetworkInfo()!=null && cm.getActiveNetworkInfo().isConnected() && cm.getActiveNetworkInfo().isAvailable())
{
return true;
}
else
{
return false;
}
}
public void download_video(int position, View btn)
{
}
public class CustomList2 extends ArrayAdapter<String>
{
View view;
int position;
Button btn;
public CustomList2(Context context, int layout_id, ArrayList<String> objects)
{
super(context, layout_id, objects);
}
#Override
public View getView(final int position, View convertView, ViewGroup view_group)
{
set_view(convertView);
this.position = position;
TextView text_view = (TextView) view.findViewById(R.id.name);
ImageView image = (ImageView) view.findViewById(R.id.img);
btn = (Button) view.findViewById(R.id.play);
prepare_btn();
text_view.setText( list_text() );
image.setImageResource(images[position]);
return view;
}
public String list_text()
{
String s = arr_videos.get( position ).replace("_", " ").replace(".m4v", "");
s = s.substring(2, s.length());
return s;
}
public void set_view(View convertView)
{
if(convertView == null)
{
LayoutInflater inflater = getLayoutInflater();
view = inflater.inflate(R.layout.customlist, null);
}
else
{
view = convertView;
}
}
public Boolean is_downloaded()
{
return arr_sdcardvideos.contains(arr_videos.get(position));
}
public void prepare_btn()
{
btn.setTag((Integer) position);
if(is_downloaded() == true)
{
btn.setText("Play ");
btn.setEnabled(true);
btn.setOnClickListener( new OnClickListener()
{
public void onClick(View btn)
{
int position = (Integer) btn.getTag();
Intent i = new Intent(VideosActivity.this, PlayVideoActivity.class);
String video_path = storage_dir + "/" + arr_videos.get(position);
Log.v("video_path", video_path);
i.putExtra("video_path", video_path);
startActivity(i);
}
});
}
else
{
btn.setText("Download ");
btn.setOnClickListener( new OnClickListener()
{
public void onClick(View btn)
{
int position = (Integer) btn.getTag();
btn.setEnabled(false);
//download_video( position, btn );
Download d = new Download();
d.start(position, (Button) btn);
}
});
}
}
}
public class Download
{
File new_video_file;
Button btn; //the progress meter needs to know what button called this. set via setter method below.
int position;
com.amazonaws.services.s3.transfer.Download download;
protected void start(int position, Button btn)
{
this.btn = (Button) btn;
this.position = position;
this.new_video_file = new File(storage_dir, arr_videos.get(position)); //local file to be writtent to
AWSCredentials credentials = new BasicAWSCredentials("xx", "xx" );
TransferManager tx = new TransferManager(credentials);
this.download = tx.download(s3_bucket, s3_dir + arr_videos.get(position), new_video_file);
download.addProgressListener(new ProgressListener()
{
public void progressChanged(final ProgressEvent pe)
{
handler.post( new Runnable()
{
#Override
public void run()
{
if ( pe.getEventCode() == ProgressEvent.COMPLETED_EVENT_CODE )
{
Download.this.onComplete();
}
else
{
Download.this.onProgressUpdate();
}
}
});
}
});
}
//protected void onProgressUpdate(Double progress)
protected void onProgressUpdate()
{
Double progress = this.download.getProgress().getPercentTransfered();
String percent = progress.intValue() + "%";
Log.v("runnable", percent);
btn.setText(percent);
Log.v("dev", progress + "");
}
protected void onComplete()
{
Log.v("dev", "download complete!!!");
set_sdcard_video_data();
adapter.notifyDataSetChanged();
// this.download.abort();
}
}
}
Your Download Thread keeps a reference to the Button. The Buttons get reused though for different list elements when you scroll. You need to find a way to update the Button in the Thread somehow. The Button in the Thread can also be null, when the list element is not visible.
Edit:
It's really not that complicated. First of all: you should use a ViewHolder, that's gonna make your life much easier. Then you could do something like that
#Override
public View getView(final int position, View convertView, ViewGroup view_group) {
View view = null;
ViewHolder holder = null;
if(convertView == null){
view = {inflate view}
view.setTag(holder = new ViewHolder());
holder.view1 = view.findViewById(...);
{get rest of the views}
}else{
view = convertView;
holder = (ViewHolder)view.getTag();
}
if(holder.getDownloadThread() != null){
holder.getDownloadThread().setButton(null);
}
...
}
You get the idea.