In my app I get a Force Close, and I don't know how to solve this. The problem is that I have a class that extends ListActivity. In this class there is a list of shops, and the user should select one of the shops. If he not select a shop and press button Back I get Force Close, because the previous class expect the name of the shop. How can I catch this error?
Here is my class for selecting a shop :
public class SelectShop extends ListActivity {
private ListView lv1;
SimpleCursorAdapter adapter = null;
Cursor cursor;
DbAdapter db;
ImageView iconshop;
private static final int ADD=Menu.FIRST;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shopselect);
iconshop = (ImageView) findViewById(R.id.iconshop);
lv1 = getListView();
DbApplication myApplication = (DbApplication) this.getApplication();
db= myApplication.getDatabaseAdapter();
cursor = db.getAllShops();
startManagingCursor(cursor);
if (cursor != null && cursor.moveToFirst()){
adapter = new SimpleCursorAdapter(this, R.layout.shopsrow, cursor,
new String[] { DbAdapter.NAME, DbAdapter.ADRESS }, new int[] {
R.id.title, R.id.address });
setListAdapter(adapter);
}else Toast.makeText(this,
"Choose Menu for adding a shop",
Toast.LENGTH_LONG).show();
lv1.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Intent j = new Intent(SelectShop.this,
com.ShoppingList.NewList.class);
Cursor c = (Cursor) parent.getAdapter().getItem(position);
j.putExtra("shop", c.getString(c.getColumnIndex(db.NAME)));
setResult(RESULT_OK, j);
finish();
}
});
}
/*Adaugarea meniului Add Shop*/
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, ADD, 0, "Add Shop").setIcon(R.drawable.additem);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case ADD:
Intent j = new Intent(SelectShop.this, Shops.class);
startActivityForResult(j, 0);
return true;
}
return false;
}
}
and in previuos class I have this:
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
switch (requestCode) {
case 0: {
Bundle b = intent.getExtras();
shopselect = b.getString("shop");
shop.setText(shopselect);
}
break;
}
}
You have to check the null condition in onActivityResult like below.
if(b != null)
{
shopselect = b.getString("shop"); shop.setText(shopselect);
}
I think you need to implement a mechanism that won't let your user get back to previous activity without choosing any item in the list. Override your onKeyDown() method, and when the user presses Back key you should check whether any item is chosen. If it's not you can throw an alert dialog to inform user what he must do to proceed. Hope this helps!
Check the result code. do your thing only if the result code is Activity.RESULT_OK.
Related
I have a List View in one activity with one info icon in custom adapter. When user taps on that info button then the next activity will open and after marking attendance in next activity when user taps the update button then the second activity should finish and first activity listview should be updated.
What i successfully did:
I have successfully mark the attendance and change the color of listview but i did that after closing the second activity and restarting the first activity. In this way the listview gets updated because of starting activity again.
What I am unable to do:
I want that when user taps on update button then only finish() will call and user returns to previous first activity with listview updated. But when i do so then the listview not get updated. I have to go back and open the activity again then the listview gets updated otherwise not. I do not want that. I also tried to notify adapter in the onResume method of first activity so that when user returns from second activity then the first activity listview adapter will be updated because of onResume method but it isn't work. Please Help
My Listview Activity Code:
public class TeacherWebserviceMainList extends Activity {
int attentedncemarkedCount = 0;
TextView addteacher;
DatabaseHandler databasehandler;
DetailsTeacherwebservice details;
String emis;
ArrayList<DetailsTeacherwebservice> addas = new ArrayList<DetailsTeacherwebservice>();
CustomAdapterTeacherWebservice cusadapter;
ArrayList<DetailsTeacherwebservice> teacherList;
private ListView listcontent = null;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.teacherwebservicemainlist );
addteacher = (TextView) findViewById(R.id.addteachermenu);
databasehandler = new DatabaseHandler(TeacherWebserviceMainList.this);
listcontent = (ListView) findViewById(R.id.teacher_list);
teacherList = databasehandler.teacherwebserviceList(emis);
Rsults();
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if(resultCode == RESULT_OK) {
String update = data.getStringExtra("update");
if(update.equals("1"))
{
//cusadapter.
CustomAdapterTeacherWebservice adapter = new CustomAdapterTeacherWebservice(this, addas);
listcontent.setAdapter(adapter);
}
}
}
}
private void Rsults() {
addas.clear();
//DatabaseHandler databaseHandler=new DatabaseHandler(this);
//ArrayList<ArrayList<Object>> data = databaseHandler.abcTeacherNew();
for (int p = 0; p < teacherList.size(); p++) {
details = new DetailsTeacherwebservice();
//ArrayList<Object> baris = data.get(p);
details.setId(teacherList.get(p).getId());
details.setTeachername(teacherList.get(p).getTeachername());
details.setTeachercnic(teacherList.get(p).getTeachercnic());
details.setTeacherno(teacherList.get(p).getTeacherno());
details.setTeachergender(teacherList.get(p).getTeachergender());
details.setAttendance(teacherList.get(p).getAttendance());
details.setTeacherattendancedetails(teacherList.get(p).getTeacherattendancedetails());
details.setAttendancedatesince(teacherList.get(p).getAttendancedatesince());
details.setAttendancetrasnferschool(teacherList.get(p).getAttendancetrasnferschool());
addas.add(details);
}
cusadapter = new CustomAdapterTeacherWebservice(TeacherWebserviceMainList.this, addas);
listcontent.setAdapter(cusadapter);
listcontent.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
}
});
}
My List Adapter Code
public class CustomAdapterTeacherWebservice extends BaseAdapter {
private static ArrayList<DetailsTeacherwebservice> searchArrayList;
DatabaseHandler databaseHandler;
private Context context;
private LayoutInflater mInflater;
public CustomAdapterTeacherWebservice(Context context, ArrayList<DetailsTeacherwebservice> results) {
searchArrayList = results;
mInflater = LayoutInflater.from(context);
databaseHandler = new DatabaseHandler(context);
}
#Override
public int getCount() {
return searchArrayList.size();
}
#Override
public Object getItem(int p) {
return searchArrayList.get(p);
}
#Override
public long getItemId(int p) {
return p;
}
public int getViewTypeCount() {
return 500;
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public View getView(final int p, View v, ViewGroup parent) {
ViewHolder holder;
context = parent.getContext();
if (v == null) {
v = mInflater
.inflate(R.layout.teacherwebserviceadapter, null);
holder = new ViewHolder();
holder.name = (TextView) v.findViewById(R.id.teacher_name);
holder.cnic = (TextView) v.findViewById(R.id.teacher_cnic);
holder.no = (TextView) v.findViewById(R.id.teacher_phone);
holder.gender = (TextView) v.findViewById(R.id.gender);
holder.status = (TextView) v.findViewById(R.id.status);
holder.info = (ImageView) v.findViewById(R.id.edit);
holder.l1 = (LinearLayout) v.findViewById(R.id.main);
v.setTag(holder);
} else {
holder = (ViewHolder) v.getTag();
}
holder.name.setText(searchArrayList.get(p).getTeachername());
holder.cnic.setText(searchArrayList.get(p).getTeachercnic());
holder.no.setText(searchArrayList.get(p).getTeacherno());
holder.gender.setText(searchArrayList.get(p).getTeachergender());
holder.status.setText(searchArrayList.get(p).getAttendance());
if (searchArrayList.get(p).getAttendance().equals("Absent"))
{
holder.l1.setBackgroundColor(Color.parseColor("#DB674D"));
}
if (searchArrayList.get(p).getAttendance().equals("Present"))
{
holder.l1.setBackgroundColor(Color.parseColor("#7EB674"));
}
if (searchArrayList.get(p).getAttendance().equals("Transfer Out"))
{
holder.l1.setBackgroundColor(Color.parseColor("#FBE87C"));
}
if (searchArrayList.get(p).getAttendance().equals("Resigned"))
{
holder.l1.setBackgroundColor(Color.parseColor("#4FC3F7"));
}
holder.info.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent view_order_intent = new Intent(context, Teacherwebservicemainlistupdate.class);
view_order_intent.putExtra("ID", searchArrayList.get(p).getId());
view_order_intent.putExtra("tname", searchArrayList.get(p).getTeachername());
view_order_intent.putExtra("tgender", searchArrayList.get(p).getTeachergender());
view_order_intent.putExtra("tcnic", searchArrayList.get(p).getTeachercnic());
view_order_intent.putExtra("tno", searchArrayList.get(p).getTeacherno());
view_order_intent.putExtra("tatt", searchArrayList.get(p).getAttendance());
view_order_intent.putExtra("tattdetails", searchArrayList.get(p).getTeacherattendancedetails());
view_order_intent.putExtra("tattdatesince", searchArrayList.get(p).getAttendancedatesince());
view_order_intent.putExtra("tatttrasnferout", searchArrayList.get(p).getAttendancetrasnferschool());
//context.startActivity(view_order_intent);
((Activity)context).startActivityForResult(view_order_intent, 1);
}
});
return v;
}
static class ViewHolder {
TextView name, cnic, no, gender,status;
ImageView info;
LinearLayout l1;
}
here in adapter code when INFO button is clicked then another activity starts in which user can update the attendance.
This is Update activity code when button clicked:
update.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
DetailsTeacherwebservice schoolinfo = new DetailsTeacherwebservice();
schoolinfo.setTeachername(teachername.getText().toString());
schoolinfo.setTeacherno(teacherno.getText().toString());
schoolinfo.setTeachercnic(teachercnic.getText().toString());
schoolinfo.setTeachergender(teachergender.getText().toString());
schoolinfo.setAttendance(teachergroupstr);
schoolinfo.setTeacherattendancedetails(absentgrpstr);
schoolinfo.setAttendancedatesince(txtDate.getText().toString());
schoolinfo.setAttendancetrasnferschool(transferOutSchool.getText().toString());
databasehandler.updateteacherwebservice(schoolinfo, emis, identity);
Toast.makeText(Teacherwebservicemainlistupdate.this, "Updated Successfully", Toast.LENGTH_SHORT).show();
Intent intent = new Intent();
intent.putExtra("update", "1");
setResult(RESULT_OK, intent);
finish();
}
}
});
I can start the listview activity again when update button is clicked but that changes the index of the list item clicked i.e. because activity starts again. How ever what i want is that if i clicked on 10th item then when next activity opens and user updates attendance then it returns back to previous activity on same index position so that the user do not have to scroll again to go back on 10th item
Add this code for list item click:
Intent i = new Intent(context, YourAcitivityName.class);
i.putExtra("position",p);
startActivityForResult(i, 1);
Add this code in update button:
Intent intent = new Intent();
intent.putExtra("update", "1");
intent.putExtra("position",getIntent().getIntExtra("position",0));
setResult(RESULT_OK, intent);
finish();
When you get back from activity to the activity where list view is implemented this method called:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if(resultCode == RESULT_OK) {
String update = data.getStringExtra("update");
if(update.equals("1"))
{
// add your code to update list view
teacherList = databasehandler.teacherwebserviceList(emis);
Rsults();
YourAdapterClassName adapter = new YourAdapterClassName(this, arrList);
listView.setAdapter(adapter);
listView.smoothScrollToPosition(getIntent().getIntExtra("position",0));
}
}
}
}
The following are two examples, the first is an example where the source for the ListView is a List (and in this case using a Custom Adapter), the second is where the source is a Cursor (using SimpleCursorAdapter)
The trap many fall into is just updating the List using something like :-
myList = method();
myAdapter.notifyDataSetChanged();
At a guess, that's the trap you've fallen into.
When what should be done is to use the List's methods to alter it (e.g. clear, add, addAll, remove).
I believe this explains the reasoning - Is Java “pass-by-reference” or “pass-by-value”?
Example 1 - List as the source :-
/**
* Build or rebuild the List of TaskData's, instantiate the
* Custom Array Adapter if needed and also notify the adapter
* if the List may have been changed.
*/
private void prepTasksCustomArrayList() {
// Determine if the adpater needs to be notified of changes
boolean notify_dataset_changed = (mCsr != null && mCustomArrayAdapter != null);
// If the List is not null then assume that it has changed
// otherwise just get the List
if (mTasks != null) {
mTasks.clear();
mTasks.addAll(dbhlpr.getAllTasks());
} else {
mTasks = dbhlpr.getAllTasks();
}
// If the adapter is null then instantiate it
if (mCustomArrayAdapter == null) {
mCustomArrayAdapter = new CustomArrayAdapter(
this,
R.layout.taskdata_item,
mTasks);
}
// Notify the adapter that the List has changed
if (notify_dataset_changed) {
mCustomArrayAdapter.notifyDataSetChanged();
}
}
Notes
This is used to both setup and alter/update the ListView that the adpater is attached to.
All that is needed is to call the method at the appropriate place/s in the code e.g. in the Activities onCreate, onResume, after onItemClick/LongClick.
e.g in onCreate :-
mTaskList = this.findViewById(R.id.tasklist); // The ListView
prepTasksCustomArrayList()
mTaskList.setAdapter(mCustomArrayAdapter)
and in onresume just (in conjunction with the 3 lines in onCreate)
prepTasksCustomArrayList()
I don't believe that this way is very common, normally you see the adapter being setup in onCreate.
mTasks.addAll(dbhlpr.getAllTasks()); is what gets the source data.
Example 2 - Cursor as the Source
/**
* Build or rebuild the List via Cursor using the bespoke layout
*/
private void prepCursorListBespoke() {
boolean swapcursor = (mCsr != null && mCursorAdapter2 != null);
if (mCursorAdapter2 == null) {
mCursorAdapter2 = new SimpleCursorAdapter(this,R.layout.taskdata_item,mCsr,
new String[]{ Datasource.TASKS_ID_COL,
Datasource.TASKS_TYPE_COL,
Datasource.TASKS_NAME_COL,
Datasource.TASKS_OWNER_COL,
Datasource.TASKS_EXPIRATION_COL},
new int[]{R.id.task_id,
R.id.task_type,
R.id.task_name,
R.id.task_owner,
R.id.task_expiration},
0);
}
if (swapcursor) {
mCursorAdapter2.swapCursor(mCsr);
}
}
Notes
The prepCursorListBespoke method is used in the same way as for example 1.
notifyDataSetChanged could be used instead of swapCursor
I use swapCursor because it's more descriptive).
However, you can only use swapCursor for Cursors.
Added
The following changes may work, roughly speaking I've applied the List example above.
i.e. Rsults is called by onResume(added) which will notify the adapter that the data has been changed.
The code hasn't been tested as there was insufficient code. (a no code for DatabaseHandler class, and b) no code for DetailsTeacherwebservice class). As such there may be errors.
Look for //++++++++++++++... comments should follow to say what has been done/changed.
public class MainActivity extends Activity {
int attentedncemarkedCount = 0;
TextView addteacher;
DatabaseHandler databasehandler;
DetailsTeacherwebservice details;
String emis;
ArrayList<DetailsTeacherwebservice> addas = new ArrayList<DetailsTeacherwebservice>();
CustomAdapterTeacherWebservice cusadapter;
ArrayList<DetailsTeacherwebservice> teacherList;
private ListView listcontent = null;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.teacherwebservicemainlist);
addteacher = (TextView) findViewById(R.id.addteachermenu);
databasehandler = new DatabaseHandler(TeacherWebserviceMainList.this);
listcontent = (ListView) findViewById(R.id.teacher_list);
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//MOVED On ItemClickListener block FROM Rsults to here.
listcontent.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
}
});
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
teacherList = databasehandler.teacherwebserviceList(emis);
Rsults();
}
// Probably don't even need onActivityResult
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if (resultCode == RESULT_OK) {
String update = data.getStringExtra("update");
if (update.equals("1")) {
//cusadapter.
//CustomAdapterTeacherWebservice adapter = new CustomAdapterTeacherWebservice(this, addas);
//+++++++++++++++++++++++++++++++++++
// Commented out
//listcontent.setAdapter(adapter);
}
}
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Added onResume to call Rsults
#Override
public void onResume() {
super.onResume();
Rsults();
}
private void Rsults() {
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ADDED 4 lines to see if the notifyDataSetChanged is required
boolean notifydschg_needed = false;
if (cusadapter != null) {
notifydschg_needed = true;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// YOU NEED TO GET THE TEACHER LIST AGAIN AS THE DB HAS CHANGED
teacherList = databasehandler.teacherwebserviceList(emis);
addas.clear();
//DatabaseHandler databaseHandler=new DatabaseHandler(this);
//ArrayList<ArrayList<Object>> data = databaseHandler.abcTeacherNew();
for (int p = 0; p < teacherList.size(); p++) {
details = new DetailsTeacherwebservice();
//ArrayList<Object> baris = data.get(p);
details.setId(teacherList.get(p).getId());
details.setTeachername(teacherList.get(p).getTeachername());
details.setTeachercnic(teacherList.get(p).getTeachercnic());
details.setTeacherno(teacherList.get(p).getTeacherno());
details.setTeachergender(teacherList.get(p).getTeachergender());
details.setAttendance(teacherList.get(p).getAttendance());
details.setTeacherattendancedetails(teacherList.get(p).getTeacherattendancedetails());
details.setAttendancedatesince(teacherList.get(p).getAttendancedatesince());
details.setAttendancetrasnferschool(teacherList.get(p).getAttendancetrasnferschool());
addas.add(details);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Just create the adapter and attach it to the listview once
if (cusadapter == null) {
cusadapter = new CustomAdapterTeacherWebservice(TeacherWebserviceMainList.this, addas);
listcontent.setAdapter(cusadapter);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Notify the adapter that the data has been changed
if(notifydschg_needed) {
cusadapter.notifyDataSetChanged();
}
}
}
// you have to set data in adapter in onResume method
#Override
protected void onResume() {
super.onResume();
}
You can use eventbus for this case:
This is an example:
In your build.gradle file
compile 'org.greenrobot:eventbus:3.0.0'
In Activity has listview:
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this); // register event
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this); // unregister event
}
#Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(EventBusInfo eventBusInfo) {
if (eventBusInfo.getProcessId() == 99) {
// eventBusInfo.getData();
notifyDataSetChanged();
}
}
In Update Activity
yourButtonFinish.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
finish();
EventBusInfo event = new EventBusInfo();
event.setProcessId(99);
//event.setData(object) //if you want get data back
EventBus.getDefault().post(event);
}
});
Class EventBusInfo
public class EventBusInfo {
private int processId;
private Object data;
public EventBusInfo(int processId, Object data) {
this.processId = processId;
this.data = data;
}
public EventBusInfo() {
}
public EventBusInfo(int processId) {
this.processId = processId;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public int getProcessId() {
return processId;
}
public void setProcessId(int processId) {
this.processId = processId;
}
}
save the list items in every change then restart the Activity of adapter with intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) to close the old ListView.
Is what I do and it works fine.
if the list it is not empty, I restart the activity with the adapter and I have a new ListView closing the previous one. Or if it is empty, I start a different activity (to not have an empty ListView)
Saving and loading the list items every time to SharedPreferences with Gson
For a reason notifyDataSetChanged() does not work good in my case so I prefer this solution.
Activity A has a listView , Activity B has a checkBox and save button.
When save button in B is clicked, it will return to Activity A. When the list in Activity A is pressed, how to show the check box is checked in Activity B if it is checked before return to A ?
Activity B
if(getIntent().getExtras()!=null) // when Activity A list is pressed
{
final String from = getIntent().getStringExtra("from");
travelFrom.setText(from);
// how to show check box is checked ?
}
save.setOnClickListener(new View.OnClickListener() { // if save button clicked, return from and outstation to A
#Override
public void onClick(View v) {
String from=travelFrom.getText().toString();
returnIntent.putExtra("from", from);
if(checkbox.isChecked()) {
returnIntent.putExtra("outstation", checkbox.getText().toString());
}
}
});
Activity A
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { // if listView is clicked
#Override
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
mClickedPosition = position;
Object o = listview.getItemAtPosition(position);
SearchResults fullObject = (SearchResults) o;
String from=fullObject.getFrom();
Intent i = new Intent(getApplication(),B.class);
i.putExtra("from",from);
startActivityForResult(i, PROJECT_REQUEST_CODE);
}
});
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { // receive from Activity B and populate ListView A
if (resultCode == RESULT_OK) {
if (requestCode == PROJECT_REQUEST_CODE) {
from=data.getStringExtra("from");
check=data.getStringExtra("outstation");
objMyCustomBaseAdapter.addNewItem(from,check); // save from and "outstation" into MySQL
}
}
}
When I press the list in A to B, the check box always not checked. How to make it check ?
Do something like implementing setOnclicklistner for checkbox. and assume an int variable to be zero. and when ever we click the checkbox increase the number by 1 every time. When we are moving from one activity to another send the data of int variable to Activity B. check Activity check the condition int variable as variable%2 if the value is equal to 1 the check box is checked. else it is not.
Assuming you have some object with this...
class MyData {
private boolean check;
public boolean getCheck() { return check; }
}
Here is some rough pseudo-code to demonstrate the concept, so not copy-paste worthy
Activity A - Pass in the boolean value that you want to the next activity
class ActivityA {
private ListView listView
onCreate() {
listView = (ListView) findViewById(R.id.list);
ArrayAdapter adapter = new ArrayAdapter();
listView.setAdapter(adapter);
listView.setOnItemClickListener( new ItemClickListener() {
onClick(int position) {
MyData listObject = adapter.getItem(position);
boolean checked = listObject.getCheck();
Intent i = new Intent(ActivityA.this, ActivityB.class);
i.putExtra("checkTheBox", check);
startActivity(i);
}
});
}
}
Activity B - Get the value out of the intent and set the checkbox to checked
class ActivityB {
private Checkbox checkbox;
onCreate() {
checkbox = (Checkbox) findViewById(R.id.checkbox);
Bundle extras = getIntent().getExtras();
if (extras != null) {
checkbox.setChecked(extras.getBooleanExtra("checkTheBox"));
}
}
}
You have to save the checked status for the selected list item when returning back from Activity B to Activity A.
In order to do that, you can simply store information in Activity A for the currently selected list item.
(for example TreeMap<View, Boolean> - item-> isSelected)
Then in onActivityResult you can set if there has been a check or not for the last selected item. When selecting again, before you create the intent you can check if this item has already been selected.
To know ActivityA ListItem is checked in ActivityB (ie CheckBox) or not. Check this below code hope this helps
ActivityA stuff
int selectedPosition;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//your UI setup and findViewById stuff
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectedPosition = position;
startActivityForResult(activityBIntent, REQ_CODE);
}
});
}
int REQ_CODE = 7;
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQ_CODE)
if (resultCode == RESULT_OK) {
adapter.changeStatus(selectedPosition, true);//update adapter
} else {
//checkbox not checked
adapter.changeStatus(selectedPosition, false);//update adapter
}
}
ActivityB stuff
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//your UI stuff
setResult(RESULT_CANCELED);//default
//check box setup and save button onclick listener
}
#Override
public void onClick(View v) {
if(v.getId()==R.id.save_button){
if (checkBox.isChecked())
setResult(RESULT_OK);
else
setResult(RESULT_CANCELED);//default
finish();//finish ActivityB and take the result to ActivityA
}
}
Mainactivity where I check the clicking of the refresh button
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Will close the drawer if the home button is pressed
if (drawerToggle.onOptionsItemSelected(item)) {
return true;
}
switch (item.getItemId()) {
case R.id.search:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
return false;
} else {
// Legacy search mode for Eclair
onSearchRequested();
return true;
}
case R.id.refresh:
startDownloadSchedule();
// TODO: resolve this
Toast.makeText(getApplication(), "Updating database", Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
private void startDownloadSchedule() {
progressBar.clearAnimation();
progressBar.setIndeterminate(true);
progressBar.setProgress(100);
progressBar.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.fade_out));
progressBar.setMax(100);
progressBar.setVisibility(View.VISIBLE);
//JsonToDatabase gets data from google sheets in json format and then saves it in a database
JsonToDatabase dataDownload = new JsonToDatabase(getApplicationContext());
dataDownload.setOnJsonToDatabaseCallback(new JsonToDatabase.JsonToDatabaseCallback() {
#Override
public void onDataLoaded() {
Toast.makeText(getApplication(), "done updating", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
TracksListFragment tracksListFragment1 = new TracksListFragment();
tracksListFragment1.onCreate(new Bundle());
}
});
dataDownload.startDataDownload();
}
TracklistFragment.class ( this is the activity whose data I want to refresh)
public class TracksListFragment extends SmoothListFragment {
//public String[] columns;
//public int[] to;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
displaydata();
}
public void displaydata() {
String[] columns = new String[]{DatabaseHelper.TABLE_COLUMN_NAME, DatabaseHelper.TABLE_COLOUMN_INFORMATION};
// THE XML DEFINED VIEWS WHICH THE DATA WILL BE BOUND TO
int[] to = new int[]{R.id.textView_track_title, R.id.textView_track_information};
DatabaseManager db = DatabaseManager.getInstance();
if (getActivity() != null) {
SimpleCursorAdapter mAdapter = new SimpleCursorAdapter(
getActivity(), R.layout.list_tracks, db.getTracks(), columns, to, CursorAdapter.NO_SELECTION);
setListAdapter(mAdapter);
Toast.makeText(getActivity(),"display data",Toast.LENGTH_SHORT).show();
}
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
String text = ((TextView) v.findViewById(R.id.textView_track_title)).getText().toString();
Intent intent = new Intent(getActivity(), TrackActivity.class);
intent.putExtra("TRACK", text);
startActivity(intent);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setEmptyText("No data present");
}
}
I am just stuck at how to display the new refreshed data. I have checked that the data gets downloaded. Any help would be appreciated. Thanks in advance.
Version the database. Add SharedPreferences for the database and increment it each time new data is added, then Call updateDb from Open helper.
In my activity I have the ActionBar with an action button new(that adds a new item on the ListView) and a ListView. The problem is that after I add some items and then I press back button, the ListView returns to the previous ListView with an item less and after one/two seconds shows the complete listviews with all items. I think the problem is something like the listview duplicate one over the previous.
Here is my activity:
public class ListNotesActivity extends ActionBarActivity {
private ArrayList<Note> notes;
private Database db;
private long lastBackPressTime = 0;
private Toast toast;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_notes);
notes = new ArrayList<Note>();
db = new Database(this);
getNotes();
ActionBar ab = getSupportActionBar();
ab.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#E89619")));
ab.setTitle("Your notes");
}
#Override
public void onBackPressed() {
if (this.lastBackPressTime < System.currentTimeMillis() - 4000) {
toast = Toast.makeText(this, "Press back again to exit", 4000);
toast.show();
this.lastBackPressTime = System.currentTimeMillis();
} else {
if (toast != null)
toast.cancel();
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.list_notes, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
switch (id) {
case R.id.action_new:
//In this activity that I start, It will save the new Item in the database and then it starts this activity again that will read the database with the new item.
Intent i = new Intent(ListNotesActivity.this,
NotesActivity.class);
i.putExtra(NEWNOTE, true);
startActivity(i);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void getNotes() {
final Toast t = Toast.makeText(this, R.string.retrieving_notes,
Toast.LENGTH_SHORT);
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
notes = db.getNotes();
Log.v("MyActivity",
"Read notes on the database: " + notes.size());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
populateList();
}
};
t.show();
task.execute();
}
public void populateList() {
NoteAdapter adapter = new NoteAdapter(this, notes);
final ListView listView = (ListView) findViewById(R.id.list_notes);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parentView, View childView,
int position, long id) {
Note note = notes.get(position);
Log.v("MyActivity",
"LISTNOTESACTIVITY: note's title: " + note.getTitle());
Bundle b = new Bundle();
b.putSerializable(EDITNOTE2, note);
Intent i = new Intent(ListNotesActivity.this,
NotesActivity.class);
i.putExtra(EDITNOTE, true);
i.putExtra(EDITNOTE2, b);
startActivity(i);
}
});
}
I hope I made me clear.
Thanks in advance!
try to remove this line from your getNotes() Method
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Your list view is update only when activity is created ( not when is resumed ) , because you call getNotes() only in onCreate(). In method getNotes(), you make asynch operation.
If you want to update immediately your list view, should take strategy like this.
Start new activity for result, and in second activity after create new item pass data back to the first.
In NotesActivity after create new item add and call this method
private void saveItem(Note note)
{
Intent data = new Intent();
// set all data from your item
data.putExtra(name, value);
setResult(RESULT_OK, data);
}
In ListNotesActivity you should start new activity by using this call
startActivityForResult(intent, 1);
And override this method
#Override
protected void onResume()
{
super.onResume();
// This call on your list view to update rows
listViewAdapter.notifyDataSetChanged();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if(resultCode == RESULT_OK && requestCode == 1)
{
Note note = new Note();
// Extract your data from intent
data.getExtra(name); // and set to note variable
// add your new item to list view adapter
listViewAdapter.addNewItem(note);
}
}
I hope this will help you.
I have a ListView, which displays a list of notes taken from a table in SQLiteDatabase with ArrayAdapter.
public class NotepadActivity extends ListActivity {
protected static final int ADD_NEW_NOTE = 0;
protected static final int EDIT_NOTE = 1;
ArrayAdapter<Note> adapter;
NotesManager manager;
private Note nNoteToDelete;
ArrayList<Note> lstAllNotes;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
findViewById(R.id.btnAddNewNote).setOnClickListener(addNewNote);
manager = new NotesManager(this);
lstAllNotes = manager.getAllNotes();
adapter = new ArrayAdapter<Note>(this, R.layout.note, lstAllNotes);
setListAdapter(adapter);
getListView().setOnItemClickListener(editNote);
registerForContextMenu(getListView());
}
When I click on an Item in this ListView, it takes this Note object to the EditNote activity:
private OnItemClickListener editNote = new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Note currNote = (Note)parent.getItemAtPosition(position);
int curr_note_id = currNote.getId();
String curr_note_title = currNote.getTitle().toString();
String curr_note_details = currNote.getDetails().toString();
Intent editNote = new Intent(NotepadActivity.this, EditNote.class);
editNote.putExtra("CURR_NOTE_ID", curr_note_id);
editNote.putExtra("CURR_NOTE_TITLE", curr_note_title);
editNote.putExtra("CURR_NOTE_DETAILS", curr_note_details);
startActivityForResult(editNote, EDIT_NOTE);
}
};
I can edit the title of the note in there and the content. When I hit the Save button, it sends back to the main activity the Strings of Title and the Details and the ID int:
public class EditNote extends Activity implements OnClickListener {
int curr_note_id;
String curr_note_title;
String curr_note_details;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.editnote);
curr_note_id = getIntent().getExtras().getInt("CURR_NOTE_ID");
curr_note_title = getIntent().getExtras().getString("CURR_NOTE_TITLE");
curr_note_details = getIntent().getExtras().getString(
"CURR_NOTE_DETAILS");
((EditText) findViewById(R.id.edtTitle)).setText(curr_note_title);
((EditText) findViewById(R.id.edtDetails)).setText(curr_note_details);
findViewById(R.id.btnSave).setOnClickListener(this);
findViewById(R.id.btnCancel).setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnSave:
String strNoteTitle = ((EditText) findViewById(R.id.edtTitle)).getText().toString().trim();
String strNoteDetails = ((EditText) findViewById(R.id.edtDetails)).getText().toString().trim();
if (!strNoteTitle.equals("")) {
Intent data = new Intent();
data.putExtra("NOTE_ID", curr_note_id);
data.putExtra("NOTE_TITLE", strNoteTitle);
data.putExtra("NOTE_DETAILS", strNoteDetails);
setResult(RESULT_OK, data);
finish();
} else {
((EditText) findViewById(R.id.edtTitle))
.setError("A note must contain a title");
}
break;
case R.id.btnCancel:
setResult(RESULT_CANCELED);
finish();
break;
}
}
}
And in the main activity it should update the DB and the ListView with the new Title, if there were changes. My code does update the DB, but I don't see the change in the ListView immediately, only if I exit the app and open it again. Here's the code (watch the second case, EDIT_NOTE):
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch (requestCode) {
case ADD_NEW_NOTE:
String noteTitle = data.getExtras().getString("NOTE_TITLE");
String noteDetails = data.getExtras().getString("NOTE_DETAILS");
Note nNewNote = new Note(-1, noteTitle, noteDetails);
adapter.add(nNewNote);
manager.addNote(nNewNote);
break;
case EDIT_NOTE:
int noteID = data.getExtras().getInt("NOTE_ID");
noteTitle = data.getExtras().getString("NOTE_TITLE");
noteDetails = data.getExtras().getString("NOTE_DETAILS");
nNewNote = new Note(noteID, noteTitle, noteDetails);
Toast.makeText(NotepadActivity.this, noteTitle + "\n" + noteDetails, Toast.LENGTH_SHORT).show();
manager.updateNote(nNewNote);
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
After manager.updateNote(nNewNote); I tried to use adapter.notifyDataSetChanged(); but that didn't work - I didn't see the change in the ListView. Perhaps I used it wrong, perhaps I should use something else...
So how can I make the ListView refresh? How can I see change immediately, without restarting the app?
Thank you!
When you return from the edit activity, set the list adapter again to refresh the ListView. You have to manually refresh the ListView each time if you want to see any updates. Hope this helps.