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.
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
}
}
I'm having an issue with saving the instance of an ArrayList of custom objects in an Activity and then retreiving it after doing some stuff in another Activity. Inside the first Activity (which has the ArrayList), there is a button to start a second activity. Inside this second Activity the user is asked to create a new object that will be added afterwards in the ArrayList of the first Activity, so that when the second Activity finishes the first Activity is shown again with a ListView of all the objects (including the last one created). The problem I'm facing is that only the last object created is being shown in the ListView.
Here is the code of the first Activity:
public class CargasMin extends AppCompatActivity implements View.OnClickListener {
RelativeLayout rl_CargasMin;
ImageButton bt_AdDep;
Button bt_CalcCargas;
ListView listView_Dep;
ArrayList<Dependencia> listaDeDependencias = new ArrayList<Dependencia>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.min_cargas);
rl_CargasMin = (RelativeLayout) findViewById(R.id.cargasMinLayout);
bt_AdDep = (ImageButton) findViewById(R.id.bt_AdDep_CargasMin);
bt_CalcCargas = (Button) findViewById(R.id.bt_CalcCargas_CargasMin);
bt_AdDep.setOnClickListener(this);
bt_CalcCargas.setOnClickListener(this);
// This seems not to be working!
if(savedInstanceState == null) { }
else {
listaDeDependencias = savedInstanceState.getParcelableArrayList("key");
}
// Get last object created
Intent intent_de_AdDep = getIntent();
Dependencia dependenciaAAdicionar = (Dependencia) intent_de_AdDep.getParcelableExtra("novaDependencia");
if(dependenciaAAdicionar == null) { }
else {
listaDeDependencias.add(dependenciaAAdicionar);
}
//Cria Adapter pra mostrar dependencias na ListView
DependenciaAdapter adapterDeDependencias = new DependenciaAdapter(this, R.layout.adapter_dependencia, listaDeDependencias);
//Seta Adapter
listView_Dep = (ListView) findViewById(R.id.listView_Dep_CargasMin);
listView_Dep.setAdapter(adapterDeDependencias);
}
#Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.bt_AdDep_CargasMin:
Intent intent_AdDep = new Intent(CargasMin.this, AdDep.class);
startActivity(intent_AdDep);
break;
case R.id.bt_CalcCargas_CargasMin:
//
break;
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
// Aqui se salva a listaDeDependencias quando a Atividade eh momentaneamente fechada.
outState.putParcelableArrayList("key", listaDeDependencias);
super.onSaveInstanceState(outState);
}
}
This is the code of my custom class Dependencia:
public class Dependencia implements Parcelable {
String nome;
int tipo;
float largura = 0;
float comprimento = 0;
float area = 0;
float perimetro = 0;
// Constructor da classe Dependencia.
public Dependencia(String nomeDep, int tipoDep) {
nome = nomeDep;
tipo = tipoDep;
}
private Dependencia(Parcel in) {
nome = in.readString();
tipo = in.readInt();
largura = in.readFloat();
comprimento = in.readFloat();
area = in.readFloat();
perimetro = in.readFloat();
}
public int describeContents() {
return 0;
}
public void writeToParcel(Parcel out, int flags) {
out.writeString(nome);
out.writeInt(tipo);
out.writeFloat(largura);
out.writeFloat(comprimento);
out.writeFloat(area);
out.writeFloat(perimetro);
}
public static final Parcelable.Creator<Dependencia> CREATOR = new Parcelable.Creator<Dependencia>() {
public Dependencia createFromParcel(Parcel in) {
return new Dependencia(in);
}
public Dependencia[] newArray(int size) {
return new Dependencia[size];
}
};
}
And this is the code of the second Activity:
public class AdDep extends AppCompatActivity implements View.OnClickListener {
RelativeLayout rl_AdDep;
EditText et_Nome;
EditText et_Largura;
EditText et_Comprimento;
EditText et_Area;
EditText et_Perimetro;
Spinner spinner_Tipo;
String vetorTipo[];
int tipoEscolhido;
Button bt_AdDep1;
Button bt_AdDep2;
Dependencia novaDependencia;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dep_ad);
rl_AdDep = (RelativeLayout)findViewById(R.id.adDepLayout);
et_Nome = (EditText) findViewById(R.id.et_Nome_AdDep);
et_Largura = (EditText) findViewById(R.id.et_Largura_AdDep);
et_Comprimento = (EditText) findViewById(R.id.et_Comprimento_AdDep);
et_Area = (EditText) findViewById(R.id.et_Area_AdDep);
et_Perimetro = (EditText) findViewById(R.id.et_Perimetro_AdDep);
spinner_Tipo = (Spinner) findViewById(R.id.spinner_Tipo_AdDep);
bt_AdDep1 = (Button) findViewById(R.id.bt_AdDep1);
bt_AdDep2 = (Button) findViewById(R.id.bt_AdDep2);
// Adicionando opcoes no spinner
vetorTipo = new String[5];
vetorTipo[0] = "Banheiro";
vetorTipo[1] = "Varanda";
vetorTipo[2] = "Cozinha/Copa/Serviço/etc.";
vetorTipo[3] = "Sala/Dormitório";
vetorTipo[4] = "Outro";
// Criando ArrayAdapter de strings pro spinner
ArrayAdapter<String> adapterTipo = new ArrayAdapter<String>(AdDep.this, android.R.layout.simple_spinner_item, vetorTipo);
// Setando o Adapter
spinner_Tipo.setAdapter(adapterTipo);
// Valor default do spinner (hint)
spinner_Tipo.setSelection(0);
bt_AdDep1.setOnClickListener(this);
bt_AdDep2.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(String.valueOf(spinner_Tipo.getSelectedItem()).equals("Banheiro"))
tipoEscolhido = 1;
else if(String.valueOf(spinner_Tipo.getSelectedItem()).equals("Varanda"))
tipoEscolhido = 2;
else if(String.valueOf(spinner_Tipo.getSelectedItem()).equals("Cozinha/Copa/Serviço/etc."))
tipoEscolhido = 3;
else if(String.valueOf(spinner_Tipo.getSelectedItem()).equals("Sala/Dormitório"))
tipoEscolhido = 4;
else if(String.valueOf(spinner_Tipo.getSelectedItem()).equals("Outro"))
tipoEscolhido = 5;
novaDependencia = new Dependencia(et_Nome.getText().toString(), tipoEscolhido);
switch(v.getId()) {
case R.id.bt_AdDep1:
novaDependencia.largura = Float.valueOf(et_Largura.getText().toString());
novaDependencia.comprimento = Float.valueOf(et_Comprimento.getText().toString());
break;
case R.id.bt_AdDep2:
novaDependencia.area = Float.valueOf(et_Area.getText().toString());
novaDependencia.perimetro = Float.valueOf(et_Perimetro.getText().toString());
break;
}
AlertDialog.Builder builder2 = new AlertDialog.Builder(v.getContext());
builder2.setMessage("Deseja adicionar T.U.E. nesta dependência?").setPositiveButton("Sim", dialogClickListener).setNegativeButton("Não", dialogClickListener).show();
}
// Objeto tipo dialog criado para perguntar se usario deseja inserir TUEs
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which){
case DialogInterface.BUTTON_POSITIVE:
//Yes button clicked
break;
case DialogInterface.BUTTON_NEGATIVE:
Intent intent_NovaDep_CargasMin = new Intent(AdDep.this, CargasMin.class);
intent_NovaDep_CargasMin.putExtra("novaDependencia", novaDependencia);
startActivity(intent_NovaDep_CargasMin);
break;
}
}
};
}
If anyone knows how to solve this, please share. Thanks.
The problem is that you're starting a new instance of the CargasMin activity from AdDep activity. Your AdDep activity should just finish and return a result back to the existing instance of CargasMin activity on the back stack for you to see all the previous list data as well.
To retrieve the new list item from AdDep as a result, use startActivityForResult()
case R.id.bt_AdDep_CargasMin:
Intent intent_AdDep = new Intent(CargasMin.this, AdDep.class);
startActivityForResult(intent_AdDep, ADD_DEP_REQUEST);
break;
where ADD_DEP_REQUEST is just a request code constant
public static final int ADD_DEP_REQUEST = 1;
Now, when AdDep is done collecting data, it returns the new data item as a result.
case DialogInterface.BUTTON_NEGATIVE:
Intent result = new Intent();
result.putExtra("novaDependencia", novaDependencia);
setResult(Activity.RESULT_OK, result);
finish();
break;
Your main CargasMin activity will then receive the new data item as
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ADD_DEP_REQUEST) {
if (resultCode == RESULT_OK) {
// Get last object created
Dependencia dependenciaAAdicionar =
(Dependencia) data.getParcelableExtra("novaDependencia");
if(dependenciaAAdicionar != null){
listaDeDependencias.add(dependenciaAAdicionar);
// Refresh Adapter pra mostrar dependenciaAAdicionar na ListView
adapterDeDependencias.notifyDataSetChanged();
}
}
}
}
Note that listaDeDependencias and adapterDeDependencias have been changed to instance members of the activity.
Your current approach would have worked if you were persisting the data to some storage (like in a file or database) but creating a new instance of CargasMin is still not recommended because the one existing on the back stack would suffice.
I have a notebook sample project and I want to add a "note counter" to it using shared preferences and each time the user adds a note increment the counter in createNote() method. I also added a TextView to show the counter, but the counter is always zero and doesnt increment by creating a new note! ! Help me please!
public class MainActivity extends ListActivity {
private static final int EDITOR_ACTIVITY_REQUEST = 1001;
private static final int MENU_DELETE_ID = 1002;
private int currentNoteId;
private NotesDataSource datasource;
List<NoteItem> notesList;
int count = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
datasource = new NotesDataSource(this);
refreshDisplay();
TextView tv = (TextView) findViewById(R.id.textView1);
tv.setText(""+count);
}
private void refreshDisplay() {
notesList = datasource.findAll();
ArrayAdapter<NoteItem> adapter =
new ArrayAdapter<NoteItem>(this, R.layout.list_item_layout, notesList);
setListAdapter(adapter);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_create) {
createNote(null);
}
return super.onOptionsItemSelected(item);
}
public void createNote(View v) {
NoteItem note = NoteItem.getNew();
Intent intent = new Intent(this, NoteEditorActivity.class);
intent.putExtra(NoteItem.KEY, note.getKey());
intent.putExtra(NoteItem.TEXT, note.getText());
startActivityForResult(intent, EDITOR_ACTIVITY_REQUEST);
int defaultValue = getPreferences(MODE_PRIVATE).getInt("count_key", count);
++defaultValue;
getPreferences(MODE_PRIVATE).edit().putInt("count_key", defaultValue).commit();
count = getPreferences(MODE_PRIVATE).getInt("count_key", count);
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
NoteItem note = notesList.get(position);
Intent intent = new Intent(this, NoteEditorActivity.class);
intent.putExtra(NoteItem.KEY, note.getKey());
intent.putExtra(NoteItem.TEXT, note.getText());
startActivityForResult(intent, EDITOR_ACTIVITY_REQUEST);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == EDITOR_ACTIVITY_REQUEST && resultCode == RESULT_OK) {
NoteItem note = new NoteItem();
note.setKey(data.getStringExtra(NoteItem.KEY));
note.setText(data.getStringExtra(NoteItem.TEXT));
datasource.update(note);
refreshDisplay();
}
}
}
Your help is appreciated. Thanks!
Based on discussion and answer given by #Rahul Tiwari...do the following modifications in your code.....
First create the instance TextView variable
//your instance variables
int count;
TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
//your code...
tv = (TextView) findViewById(R.id.textView1);
count = getSharedPreferences("NAME_FOR_SHARED_PREFERENCES", Context.MODE_PRIVATE).getInt("count_key", 0);
updateTextView();
}
void updateTextView(){
tv.setText(""+count);
}
//your code till here....
public void createNote(View v) {
NoteItem note = NoteItem.getNew();
SharedPreferences sharedPref = getSharedPreferences("NAME_FOR_SHARED_PREFERENCES", Context.MODE_PRIVATE);
sharedPref.edit().putInt("count_key", ++count).commit();
updateTextView()
/*for intial testing commenting this code block
Intent intent = new Intent(this, NoteEditorActivity.class);
intent.putExtra(NoteItem.KEY, note.getKey());
intent.putExtra(NoteItem.TEXT, note.getText());
startActivityForResult(intent, EDITOR_ACTIVITY_REQUEST);
*/
}
//your code.
Then you can start app multiple times and check want is the count value.
Note: When naming your shared preference files, you should use a name
that's uniquely identifiable to your app, such as
"com.example.myapp.PREFERENCE_FILE_KEY" for more detail refer
your counter is not being refreshed as you are not changing text in your text view after changing the count.
you need to use
TextView tv = (TextView) findViewById(R.id.textView1);
tv.setText(""+count);
at the end of your createNote function
use getDefaultSharedPreferences to access your shared preference across activities in your app. refer this answer for example.
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.