I have One activity in which I am reading JSONData and list in in recycler View.
I have implemented deleting data onLongClick Listener.
On click Listener I am going to Details Activity for that item.
There I have a title, image view button for edit title and button for removing Item.`
The problem is that whether I try to remove or edit title, it does not working when get back to my first Activity.
I think I do not load data in adapter properly at the main activity.
But I do not how to do it better, any solution?
Here is my Main Activity
public class MainActivity extends AppCompatActivity {
FloatingActionButton myFab;
ArrayList<ApiModel> mObjects = new ArrayList<>();
int i = 0;
final String PHOTOS_URL = "http://jsonplaceholder.typicode.com/photos";
List<ApiModel> objects = new ArrayList<>();
private RecyclerView recyclerView;
private MyAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myFab = findViewById(R.id.fab);
myFab.setImageResource(R.drawable.add);
initRecyclerView();
adapter.setData(mObjects);
adapter.notifyDataSetChanged();
//TODO: CHECK WHY NOT WORK DELETE
checkToDeleteOrRename();
adapter.notifyDataSetChanged();
getJsonObjects();
adapter.notifyDataSetChanged();
myFab.setOnClickListener(v -> {
Intent intent = new Intent(MainActivity.this, SendPhoto.class);
startActivity(intent);
});
}
private void checkToDeleteOrRename() {
Intent intentChange = getIntent();
String flag = intentChange.getStringExtra(FLAG_CHANGE);
String flagDelete = intentChange.getStringExtra(FLAG_DELETED);
try {
if (flag.equals(CHANGED)) {
String oldTitle = intentChange.getStringExtra(OLD_TITLE);
String newTitle = intentChange.getStringExtra(NEW_TITLE);
adapter.changeUserName(oldTitle, newTitle);
}
if(flagDelete.equals(DELETED)) {
String userToDelete = intentChange.getStringExtra(USER_DELETED);
adapter.remove(userToDelete);
}
} catch (Exception ex) {
return;
}
}
private void initRecyclerView() {
recyclerView = findViewById(R.id.myRecyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
adapter = new MyAdapter(this.getApplicationContext());
recyclerView.setAdapter(adapter);
}
public void getJsonObjects() {
AsyncHttpClient client = new AsyncHttpClient();
client.get(PHOTOS_URL, new JsonHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
objects = fromJson(response);
adapter.notifyDataSetChanged();
}
#Override
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
Toast.makeText(MainActivity.this, "Немате активна Интернет Конекција", Toast.LENGTH_LONG).show();
}
});
}
public ArrayList<ApiModel> fromJson(JSONArray jsonArray) {
try {
for (int i = 0; i < jsonArray.length(); i++) {
try {
JSONObject jsonObject = jsonArray.getJSONObject(i);
ApiModel photoData = new ApiModel();
photoData.mTitle = jsonObject.getString("title");
photoData.Url = jsonObject.getString("url");
photoData.thumbnailUrl = jsonObject.getString("thumbnailUrl");
mObjects.add(photoData);
adapter.notifyDataSetChanged();
} catch (JSONException e1) {
e1.printStackTrace();
}
}
} catch (Exception ex) {
}
return mObjects;
}
}
Here is my delete and edit title methods in Second Activity
public void deleteThis(View view) {
AlertDialog.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder = new AlertDialog.Builder(this, android.R.style.Theme_Material_Dialog_Alert);
} else {
builder = new AlertDialog.Builder(this);
}
builder.setTitle("Delete entry")
.setMessage("Are you sure you want to delete this entry?")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent deleteIntent = new Intent(SecondActivity.this, MainActivity.class);
deleteIntent.putExtra(FLAG_DELETED, DELETED);
deleteIntent.putExtra(USER_DELETED, mTextView.getText().toString());
mSecondActivity.startActivity(deleteIntent);
Toast.makeText(mSecondActivity, "User deleted", Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
public void editTitle(View view) {
DialogFragmentClass dialogFragment = new DialogFragmentClass();
dialogFragment.show(getFragmentManager(),"DIALOG");
}
And here are my methods to remove by title and edit title in my adapter
public void remove(String userName) {
for (ApiModel model: data ) {
if(model.getmTitle() .equals(userName)) {
data.remove(model);
notifyDataSetChanged();
}
}
}
public void changeUserName(String oldUserName, String newUsername){
for (ApiModel model: data ) {
if(model.getmTitle().equals(oldUserName)){
model.setTitle(newUsername);
this.notifyDataSetChanged();
}
}
}
One way to solve your problem is by starting the Second Activity with startActivityForResult and depending upon the action taken by the user on Second Activity put the extras in the intent and call setResult and below that call finish(), then your MainActivity's onActivityResult will get called. Inside onActivityResult you can call your function checkToDeleteOrRename(Intent intent), intent is basically that you receive inside onActivityResult as an argument. Hope this will help you!!!.
you go to another activity by clicking an item in recyclerview
use staractivityforresult to goto another 2ndactivity
also pass positon of item using put extra
and use onactivityforresult inthe 1stctivity that sets the adapter
from 2nd activity if edit or delete done use setresult to pass back edited , delete ,position params using putextra
you will get these value in 1st activity in onactivityresult
using the position, change value in the arraylist accordingly and call notifydatasetchanged
Related
My app uses a firebase RecyclerAdapter to display "plant" entities in an activity.
I made it so that if I longclick on an entity displayed in Cardview format using a ViewHolder and the RecyclerAdapter it will prompt to perform a delete and delete the plant entity + image on the firebase database and storage. Deleting and adding plants work without a hitch on the backend as I can confirm this on my firebase database.
However, when I delete a "plant" entity and add a new one, the CardView shows the previous or another image. Deleting the app and reinstalling it seems to fix the problem, because of this I think it might have to do with the local cache.
PlantActivity.java (where the plants are loaded)
I think this might be solved if there was some way to refresh the activity in some way or the RecyclerAdapter... although i've tried many things already
public class PlantActivity extends AppCompatActivity {
private static final int ADD_REQUEST = 101;
private static final String TAG = "PlantActivityView";
private DatabaseReference mDatabaseReference;
private FirebaseRecyclerAdapter plantAdapter;
private PlantDAO mPlantDAO;
private UserDAO mUserDAO;
private CoordinatorLayout coordinatorLayout;
#Override
protected void onStart() {
super.onStart();
if(!mUserDAO.isLoggedIn()){
finish();
startActivity(new Intent(PlantActivity.this, LoginActivity.class));
}
plantAdapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
plantAdapter.stopListening();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_plant_view);
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
mDatabaseReference = FirebaseDatabase.getInstance().getReference();
mPlantDAO = new PlantDAO(mDatabaseReference);
mUserDAO = new UserDAO();
//make custom appcompat toolbar to replace actionbar and add logout item
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
coordinatorLayout = findViewById(R.id.plant_coordinator);
providePlantsOfCurrentUser();
findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(),PlantAddActivity.class);
startActivityForResult(intent, ADD_REQUEST);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.menuLogout:
mUserDAO.getAuth().signOut();
finish();
startActivity(new Intent(PlantActivity.this,LoginActivity.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Snackbar GoodResultSnackbar = Snackbar.make(coordinatorLayout,"PLANT ADDED",Snackbar.LENGTH_SHORT);
Snackbar BadResultSnackbar = Snackbar.make(coordinatorLayout,"PLANT ADD FAILED",Snackbar.LENGTH_SHORT);
if(requestCode == ADD_REQUEST){
if(resultCode == Activity.RESULT_OK){
GoodResultSnackbar.show();
} else if(resultCode == Activity.RESULT_CANCELED){
BadResultSnackbar.show();
}
}
super.onActivityResult(requestCode, resultCode, data);
}
public void providePlantsOfCurrentUser(){
FirebaseRecyclerOptions<Plant> options = new FirebaseRecyclerOptions.Builder<Plant>().setQuery(mPlantDAO.currentUserPlantsQuery(), Plant.class).build();
plantAdapter = new FirebaseRecyclerAdapter<Plant,PlantViewHolder>(options) {
#NonNull
#Override
public PlantViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.cardview_item_plant, parent, false);
return new PlantViewHolder(view);
}
#Override
protected void onBindViewHolder(#NonNull final PlantViewHolder holder, final int position, #NonNull final Plant model) {
StorageReference localstorage = FirebaseStorage.getInstance().getReferenceFromUrl(model.getImageLocation());
String plantText = /*model.getPlantID() + ": " + */ model.getPlanttype();
holder.tv_plant_name.setText(plantText);
//image implementation
GlideApp.with(getApplicationContext()).load(localstorage).into(holder.img_plant_thumbnail);
holder.dialogClickListener = new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which){
case DialogInterface.BUTTON_POSITIVE:
mPlantDAO.deletePlant(model.getPlantID());
plantAdapter.notifyDataSetChanged();
break;
case DialogInterface.BUTTON_NEGATIVE:
//Return
break;
}
}
};
holder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//passing data with intent to PlantDetailActivity instance
Intent intent = new Intent(getApplicationContext(), PlantDetailActivity.class);
intent.putExtra("plantID", model.getPlantID());
intent.putExtra("planttype", model.getPlanttype());
//image implementation
intent.putExtra("image_url", model.getImageLocation());
//start the activity
startActivity(intent);
}
});
holder.cardView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
showDeleteDialog(holder);
return true;
}
});
}
};
RecyclerView recyclerView = findViewById(R.id.recyclerview_id);
recyclerView.setAdapter(plantAdapter);
recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
}
private void showDeleteDialog(PlantViewHolder holder){
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Delete this plant?").setPositiveButton("Yes", holder.dialogClickListener)
.setNegativeButton("Cancel", holder.dialogClickListener).show();
}
}
The position and model are final on the onBindViewHolder method
The viewholder can be final, but not the data or the position
Use holder.getAdapterPosition() to get the position inside annonymous interfaces like click listeners
And then get the data using getItem() method from the adapter class
The last answer by #cutiko definitely helped! But I think I realize the problem. I was saving my plantID string attribute (of new Plant object) in this fashion:
"plant_" + count() of "plants" in database + "_" + ID of the current user + ".jpg"
The problem this causes is that when I delete a plant entity and add another this could cause 2 plant entities in the database to have the same ID which causes strange behavior.
I will solve this by instead of deleting a plant from the database, changing a new attribute's("active") to false and not showing these in the FirebaseRecyclerAdapter
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.
I have an activity with multiple EditText, after entered data and click button SAVE for save them in Database(Mysql) it open Fragment which have ListView populated with this data from database.
PROBLEM:
ListView isn't showing new data that I have entered in activity!!!, even the new data is added im my ArrayList correctly.
But when I start this Fragment for the second time it shows the Listview with new data correctly.
My Fragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_liste_symbole_monetaire, container, false);
symbolMonList.clear();
lv = (SwipeMenuListView) rootView.findViewById(R.id.lv_liste_symboleMon);
adapter = new SymbMoneLvAdapter(getActivity());
FloatingActionButton btn = (FloatingActionButton) rootView.findViewById(R.id.btnAjoutAjoutSymboleMon);
btn.setOnClickListener(new android.view.View.OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent = new Intent(getActivity(), AjouterSymbMoneActivity.class);
startActivity(intent);
}
});
deleteItemLv();
getListSymbolMon();
return rootView;
}
public void deleteItemLv(){
SwipeMenuCreator 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.GRAY));
// set item width
openItem.setWidth(dp2px(90));
// set item title
openItem.setTitle("Ouvrir");
// set item title fontsize
openItem.setTitleSize(18);
// set item title font color
openItem.setTitleColor(Color.WHITE);
// add to menu
menu.addMenuItem(openItem);
// create "delete" item
SwipeMenuItem deleteItem = new SwipeMenuItem(
getActivity());
// set item background
deleteItem.setBackground(new ColorDrawable(Color.rgb(0xC9, 0xC9,
0xCE)));
// set item width
deleteItem.setWidth(dp2px(90));
// set a icon
deleteItem.setIcon(R.drawable.ic_delete);
// add to menu
menu.addMenuItem(deleteItem);
}
};
lv.setMenuCreator(creator);
lv.setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
switch (index) {
case 0:
//Ouvrir item
break;
case 1:
deleteItemDialog(position);
break;
}
// false : close the menu; true : not close the menu
return false;
}
});
}
public int dp2px(int dp) {
DisplayMetrics displayMetrics = getActivity().getResources().getDisplayMetrics();
int px = Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
return px;
}
//Dialog delete item:
public void deleteItemDialog(final int position){
Toast toast = Toast.makeText(getActivity(), "size:"+position, Toast.LENGTH_LONG);
toast.show();
Toast toat = Toast.makeText(getActivity(), "sizeTotal:"+symbolMonList.size(), Toast.LENGTH_LONG);
toat.show();
Toast oast = Toast.makeText(getActivity(), "code:"+symbolMonList.get(position).getCode(), Toast.LENGTH_LONG);
oast.show();
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
getActivity() );
alertDialogBuilder.setTitle("Supprimer");
alertDialogBuilder.setMessage("Voulez vous supprimer ce symbole monétaire?");
alertDialogBuilder
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
String Code = symbolMonList.get(position).getCode();
Call<Void> api =API.deleteSymboleMon("delete", Code);
api.enqueue(new Callback<Void>() {
#Override
public void onResponse(Call<Void> call, Response<Void> response) {
if(response.isSuccessful()){
Toast toast = Toast.makeText(getActivity(), "Symbole Monétaire supprimé", Toast.LENGTH_LONG);
toast.show();
symbolMonList.remove(position);
adapter.notifyDataSetChanged();
}else {
}
}
#Override
public void onFailure(Call<Void> call, Throwable t) {
}
});
}
}
)
.setNegativeButton("Annuler", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
}
);
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
//Get liste des SM
private void getListSymbolMon(){
final ProgressDialog mProgressDialog = new ProgressDialog(getActivity());
mProgressDialog.setIndeterminate(true);
mProgressDialog.setMessage("Chargement en cours...");
Call<List<SymbMoneItems>> api =API.getListSymbolMon();
api.enqueue(new Callback<List<SymbMoneItems>>() {
#Override
public void onResponse(Call<List<SymbMoneItems>> call, Response<List<SymbMoneItems>> response) {
if (response.isSuccessful()){
List<SymbMoneItems> List = response.body();
addListSymbolMon(List);
if (mProgressDialog.isShowing())
mProgressDialog.dismiss();
}else{
if (mProgressDialog.isShowing())
mProgressDialog.dismiss();
Toast toast = Toast.makeText(getActivity(), "Erreur", Toast.LENGTH_LONG);
toast.show();
}
}
#Override
public void onFailure(Call<List<SymbMoneItems>> call, Throwable t) {
Toast toast = Toast.makeText(getActivity(), "Erreur "+t, Toast.LENGTH_LONG);
toast.show();
if (mProgressDialog.isShowing())
mProgressDialog.dismiss();
}
});
}
public void addListSymbolMon(List<SymbMoneItems> lem){
for (int i=0;i< lem.size();i ++){
SymbMoneItems fac = lem.get(i);
symbolMonList.add(fac);
}
adapter.addAll(symbolMonList);
adapter.notifyDataSetChanged();
lv.setAdapter(adapter);
}
in my Adapter
public void addAll(ArrayList<SymbMoneItems> result) {
this.listSymb = result;
this.notifyDataSetChanged();
}
Thanks for any help.
Setting data using "=" doesn't actually have any change on dataset for adapter.
Change your addAll() method like below:
public void addAll(ArrayList<SymbMoneItems> result) {
this.listSymb.clear();
this.listSymb.addAll(result);
this.notifyDataSetChanged();
}
I have an activity and a fragment
In my activity i have button in my action bar ,on button click a dialog box is popup , in that i have a listview.
If i select any item from that list , that data goes to fragment , and based on that data from activity my fragment listview should be shown
e.g. if i select Technology , technology id =1 should pass in my query parameter and based on that my fragment listview should appear.
everytime i select different item from list my fragment listview should be updated.
But my problem is that i am not getting any data in fragment and my list is not getting updated
Mainactivity.java
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem actionViewItem = menu.findItem(R.id.miActionButton);
// Retrieve the action-view from menu
View v = MenuItemCompat.getActionView(actionViewItem);
// Find the button within action-view
Button b = (Button) v.findViewById(R.id.btnCustomAction);
// Handle button click here
b.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
showDialog(CUSTOM_DIALOG_ID);
}
});
return super.onPrepareOptionsMenu(menu);
}
#Override
public Dialog onCreateDialog(int id) {
Dialog dialog = null;
switch (id) {
case CUSTOM_DIALOG_ID:
dialog = new Dialog(this);
dialog.setContentView(R.layout.dialoglayout);
dialog.setTitle("Select Category");
dialog.setCancelable(true);
dialog.setCanceledOnTouchOutside(true);
dialog.setOnCancelListener(new OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
}
});
dialog.setOnDismissListener(new OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
// TODO Auto-generated method stub
}
});
// Prepare ListView in dialog
dialog_ListView = (ListView) dialog.findViewById(R.id.dialoglist);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, listContent);
dialog_ListView.setAdapter(adapter);
dialog_ListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// TODO Auto-generated method stub
// i = (int) parent.getItemIdAtPosition(position);
category_name = (String) parent.getItemAtPosition(position);
Log.d("category name", category_name);
if(category_name.equals("a"))
{
cat_id=1;
}
if(category_name.equals("b"))
{
cat_id=2;
}
if(category_name.equals("c"))
{
cat_id=3;
}
if(category_name.equals("d"))
{
cat_id=4;
}
if(category_name.equals("e"))
{
cat_id=5;
}
if(category_name.equals("f"))
{
cat_id=6;
}
Log.d("id",""+cat_id);
dismissDialog(CUSTOM_DIALOG_ID);
}
});
break;
}
return dialog;
}
public int getMyData() {
return cat_id;
}
Fragment.java :
public String param;
public String url;
public int cat_id;
Mainactivity activity = (Mainactivity) getActivity();
int myDataFromActivity = activity.getMyData();
cat_id = myDataFromActivity;
Log.d("Category_id", "" + cat_id);
Map<String, String> map1 = new HashMap<String, String>();
param = "?cat_id=" + cat_id;
//URL is fake , original url is working fine.
url = "http://www.abbcd.com/xyz/webservices/data/getAllData.php"
+ param;
map1.put("url", url);
new MultiPartRequester(mainActivity, map1,
NetUtils.RequestCode.GET_ALL_DATA,
this).execute();
Updated Part :
#Override
public void updateFragmentList(int catId) {
// TODO Auto-generated method stub
param = "?cat_id=" + catId;
url = "http://www.abbcd.com/xyz/webservices/data/getAllData.php"+ param;
Map<String, String> map1 = new HashMap<String, String>();
map1.put("url", url);
new MultiPartRequester(mainActivity, map1,
NetUtils.GET_DATA, this)
.execute();
}
The good approach for communication between Activity and Fragment is Listeners. When you want to update fragment, use the listener and update the fragment. Create the interface in MainActivity
Listener
public interface FragmentListener {
void updateFragmentList(int catId);
}
Implement in Fragment as
public class MyFragment extends Fragment implements MainActivity.FragmentListener
then in onActivityCreated of Fragment
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
((MainActivity) getActivity()).setFragmentListener(this);
}
MainActivity
public void setFragmentListener(FragmentListener listener)
{
this.fragmentListener = listener;
}
public void sendDataToFragment(int catId) {
this.fragmentListener.updateFragmentList(catId);
}
Hope this helps.
UPDATE
Sending data to fragment using this.fragmentListener.updateFragmentList(catId);, create the method in Fragment as ``
public void updateFragmentList(int catId){
//Here update your listview with cat id
}
use static global variable in activity
public static int cat_id = 0;
access cat_id in fragment like below
Map<String, String> map1 = new HashMap<String, String>();
param = "?cat_id=" + activity.cat_id;
or do below changes in your getMyData method
public int getMyData() {
return cat_id;
}
EDITED:
another approach finally work, call your fragment method from activity ans pass cat_id in method. instead of ExampleFragment use your fragment name.
ExampleFragment fragment = (ExampleFragment) getFragmentManager().findFragmentById(R.id.example_fragment);
fragment.mymethod(cat_id);
Hi I was wondering how I can get my Search Activity to return a result back to the Activity that started it.
I currently have a Search Dialog implemented (meaning the search Activity starts once the Search button on the phone is clicked).
Here is my code for the Search activity which is a list view.
public class ItemFinder extends ListActivity {
public static final int REQUEST_CODE = 1; // get it?
Vector<String> upcCodes;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
upcCodes = new Vector<String>();
ListView lv = (ListView) findViewById(android.R.id.list);
lv.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> a, View v, int position,
long id) {
String upc = upcCodes.elementAt(position);
setResult(RESULT_OK);
}
});
// Get the intent, verify the action and get the query
Intent intent = getIntent();
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
String query = intent.getStringExtra(SearchManager.QUERY);
ProgressDialog dialog = ProgressDialog.show(ItemFinder.this, "Searching",
"Searching. Please wait...", true);
performSearch(query);
dialog.hide();
dialog.dismiss();
}
}
public void performSearch(String query){
String result = new SmartShopClient().SearchItems(query);
List<String> dataList = new ArrayList<String>();
String _parsedResult[] = result.split("\\n");
for( int i = 0; i<_parsedResult.length; i++){
String _splitData[] = _parsedResult[i].split("\\|");
String itemName = _splitData[0];
String itemUPC = _splitData[1];
dataList.add(itemName);
upcCodes.add(itemUPC);
}
ArrayAdapter<String> arr = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, dataList);
this.setListAdapter(arr);
}
}
So the search is working all fine and dandy, but I want it so when I click one of the results in the ListView, for it to return data back to the main activity with some data, say the name of the clicked searched result.
Thanks.
What you want to do is launch the search using startActivityForResult. See an explanation here.
This way, you can pass your search results back to the activity which launched it.
That would happen in your setOnItemClickListener method, where you could launch an explicit intent naming the desired activity with extra data.
Edit : I'm not quite sure of how startActivityForResult() would be implemented since we're talking about the search activity of the application, meaning it's launched by the Android search specific module ; that's why i suggested the above solution.
I ended up doing this:
public boolean onSearchRequested() {
askSearchQuery();
return true;
}
public void sendSearchRequest(String query){
Intent mIntent = new Intent(this, ItemFinder.class);
mIntent.setAction(Intent.ACTION_SEARCH);
mIntent.putExtra(SearchManager.QUERY, query);
startActivityForResult(mIntent, ItemFinder.REQUEST_CODE);
}
public void askSearchQuery() {
final EditText input = new EditText(SmartShop.this);
AlertDialog.Builder adb = new AlertDialog.Builder(SmartShop.this);
adb.setTitle("Search Items");
adb.setMessage("Please input the name of the item you are looking for.");
adb.setView(input);
adb.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
Editable upc = input.getText();
sendSearchRequest(upc.toString());
dialog.cancel();
}
});
adb.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
adb.create().show();
}
And then I hooked the
protected void onActivityResult (int requestCode, int resultCode, Intent data) {