In my App I have stored some mockdata to show at the starting of the app. Now I have another option to add data into Realm database. But in my app, all the duplicate data is stored within the database. For Example I have three data in setRealmData() method. within this method I created same data with similar information. This data is checked perfectly. But whenever I tried to add a new data with simialer name it also stored within the app, which I do not want actually. How can I duplicate check in with preload data to new data in Realm.
My Activity Class is
public class MyColleaguesPage extends AppCompatActivity implements MyColleaguesAdapter.ColleagueListListener{
private RecyclerView recyclerView;
private MyColleaguesAdapter adapter;
private Realm colleagueRealm;
private RealmResults<MyColleagueModel> dataResult;
private static final String DIALOG_TAG = "EmployeeDialog";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mycolleagues_layout);
// Showing and Enabling clicks on the Home/Up button
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
colleagueRealm = Realm.getDefaultInstance();
recyclerView = (RecyclerView) findViewById(R.id.colleagues_recycler);
setUpRecycler();
if (!Prefs.with(this).getPreLoad()) {
setRealmData();
}
showAllPersons();
}
private void showAllPersons() {
dataResult = colleagueRealm.where(MyColleagueModel.class).findAll();
setAdapter(dataResult);
adapter.notifyDataSetChanged();
}
private void setAdapter(RealmResults<MyColleagueModel> results) {
adapter = new MyColleaguesAdapter(this, colleagueRealm.where(MyColleagueModel.class).findAllSortedAsync("id"),this);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
private void setUpRecycler() {
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
recyclerView.setHasFixedSize(true);
// use a linear layout manager since the cards are vertically scrollable
final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
}
private void setRealmData(){
List<MyColleagueModel> colleague = new ArrayList<>();
MyColleagueModel model = new MyColleagueModel();
model.setId(1);
model.setName("Name1");
model.setCompany("Comapny1");
model.setTitle("Title1");
colleague.add(model);
model = new MyColleagueModel();
model.setId(2);
model.setName("Name2");
model.setCompany("Comapny2");
model.setTitle("Title1");
colleague.add(model);
model = new MyColleagueModel();
model.setId(2);
model.setName("Name2");
model.setCompany("Comapny2");
model.setTitle("Title1");
colleague.add(model);
model = new MyColleagueModel();
model.setId(3);
model.setName("Name3");
model.setCompany("Comapny3");
model.setTitle("Title3");
colleague.add(model);
for (MyColleagueModel realmModel : colleague) {
// Persist the colleague data
colleagueRealm.beginTransaction();
colleagueRealm.copyToRealmOrUpdate(realmModel);
colleagueRealm.commitTransaction();
}
Prefs.with(this).setPreLoad(true);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.recycler_menu, menu);
final MenuItem item = menu.findItem(R.id.search);
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();
if (id == android.R.id.home) {
finish();
}
//onOptionsItemSelected(MenuItem item) add will open dialog box, which allows user to fill required data
if (id == R.id.addColleague) {
showAlertDialog();
return true;
}
return super.onOptionsItemSelected(item);
}
private void showAlertDialog() {
EditColleagueFragment dialog = new EditColleagueFragment();
//dialog.setPositiveButtonClickListener(this);
dialog.show(getSupportFragmentManager(), DIALOG_TAG);
//adapter.notifyDataSetChanged();
}
#Override
protected void onDestroy() {
if (colleagueRealm!= null)
colleagueRealm.close();
super.onDestroy();
}
}
My EditDialog Fragment Class is
public class EditColleagueFragment extends DialogFragment {
private EditText id;
private EditText name;
private EditText role;
private EditText company;
private EditText mobile;
private EditText email;
private EditText department;
private View view;
private LayoutInflater inflater;
private Realm mRealm;
/*public interface onSaveClickListener {
void onSaved();
}
private onSaveClickListener mSaveClickListener;
public void setPositiveButtonClickListener(onSaveClickListener listener){
mSaveClickListener=listener;
}*/
public EditColleagueFragment() {
}
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
inflater = getActivity().getLayoutInflater();
view = inflater.inflate(R.layout.edit_my_colleague, null);
id = (EditText) view.findViewById(R.id.id);
name = (EditText) view.findViewById(R.id.name);
role = (EditText) view.findViewById(R.id.role);
company = (EditText) view.findViewById(R.id.company);
mobile = (EditText) view.findViewById(R.id.mobile);
email = (EditText) view.findViewById(R.id.email);
department= (EditText) view.findViewById(R.id.department);
AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity());
dialog.setTitle("Add Colleague");
dialog.setView(view);
dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.cancel();
}
});
dialog.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
savePerson();
}
});
return dialog.create();
}
private void savePerson() {
mRealm = Realm.getDefaultInstance();
mRealm.beginTransaction();
MyColleagueModel model=new MyColleagueModel();
model.setId(id.getId());
model.setName(name.getText().toString());
model.setTitle(role.getText().toString());
model.setCompany(company.getText().toString());
model.setMobile(mobile.getText().toString());
model.setEmail(email.getText().toString());
model.setDepartment(department.getText().toString());
mRealm.copyToRealmOrUpdate(model);
mRealm.commitTransaction();
mRealm.close();
}
}
The way to avoid duplication of data using the Realm Mobile Platform is to use primary keys.
Normally, all insertions and updates are preserved when synchronizing data between clients, but often multiple clients want to insert data that is logically identical. To ensure that those insertions are collapsed into single objects, you can use a primary key column on the model by which the objects can be identified on both clients. If two clients each insert an object with the same primary key value, the objects will be considered logically the same, and you will end up with just the one object after synchronization.
You haven't shared your model, but it looks like there is an "ID" field — that could serve as the primary key. :-)
Note that if you are only making local changes (no synchronization), primary key conflicts will result in an error being thrown, and you manually have to handle the case of preexisting objects.
If using primary keys is inconvenient for your use case, you always have the option to wait for download to complete and then manually clean up the database — just make sure that clients are able to make the same decisions about which object to discard, so as to avoid throwing away more than necessary.
try use code below
public <E extends RealmModel> boolean isDataExist(Class<E> eClass, int id) {
E data = colleagueRealm.where(eClass).equalTo("id", id).findFirst();
return data != null;
}
private void initData(){
if(isDataExist(MyColleagueModel.class, id.getText().toString())){
// data exist
}else{
// insert new
}
Related
How do I write Shared-preference Code that is using Firebase for User authentication and the data that is saved by a user is only accessible for them?
My current application Saves a note and displays it which is the main thing needed in my project but when a user logs out and new user logs in he/she can also view the data so the data is not private. My sir suggested to make nodes for users using shared preference but i couldn't find any solutions
HomeActivity:
public class HomeActivity extends AppCompatActivity {
EditText Descriptionholder;
Button Savebtn;
DatabaseReference DatabaseNote;
ListView listViewNotes;
List<PrivateNote> privateNoteList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
DatabaseNote = FirebaseDatabase.getInstance().getReference("privatenote");
Descriptionholder = findViewById(R.id.description2);
Savebtn = findViewById(R.id.buttonsave);
listViewNotes= findViewById(R.id.listViewPrivate);
privateNoteList = new ArrayList<>();
Savebtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
addnote();
}
});
listViewNotes.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) {
PrivateNote privateNote = privateNoteList.get(i); //confusion
showUpdateDialog(privateNote.getNoteId(),privateNote.getNoteDescription());
return false;
}
});
}
public boolean onCreateOptionsMenu (Menu menu){
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.side, menu);
return true;
}
#Override
public boolean onOptionsItemSelected (MenuItem item){
switch (item.getItemId()) {
case R.id.item1:
FirebaseAuth.getInstance().signOut();
finish();
startActivity(new Intent(new Intent(this, MainActivity.class)));
Toast.makeText(this, "Logged out ", Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
protected void onStart() {
super.onStart();
DatabaseNote.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
privateNoteList.clear();
for (DataSnapshot privateSnapshot: dataSnapshot.getChildren() ){
PrivateNote privateNote = privateSnapshot.getValue(PrivateNote.class);
privateNoteList.add(privateNote);
}
PrivateList adapter = new PrivateList(HomeActivity.this,privateNoteList);
listViewNotes.setAdapter(adapter);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void showUpdateDialog(final String noteId, String noteDescription){
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
LayoutInflater inflater = getLayoutInflater();
final View dialogview = inflater.inflate(R.layout.update_dialouge,null);
dialogBuilder.setView(dialogview);
final EditText editDescription = dialogview.findViewById(R.id.editDescription);
final Button buttonUpdate = dialogview.findViewById(R.id.buttonUpdate);
final Button buttonDelete = dialogview.findViewById(R.id.buttonDelete);
dialogBuilder.setTitle("Updating Note: " +noteDescription);
final AlertDialog alertDialog = dialogBuilder.create();
alertDialog.show();
buttonUpdate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String description = editDescription.getText().toString().trim();
if (TextUtils.isEmpty(description)){
editDescription.setError(" New information required");
return;
}
updatePrivateNote(noteId,description);
alertDialog.dismiss();
}
});
buttonDelete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
deletePrivateNote(noteId);
}
});
}
private void deletePrivateNote(String noteId) {
DatabaseReference drPrivateNote = FirebaseDatabase.getInstance().getReference("privatenote").child(noteId);
drPrivateNote.removeValue();
Toast.makeText(this, " Note Deleted", Toast.LENGTH_SHORT).show();
}
private boolean updatePrivateNote(String id,String description){
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("privatenote").child(id);
PrivateNote privateNote = new PrivateNote(id,description);
databaseReference.setValue(privateNote);
Toast.makeText(this, " Note Updated", Toast.LENGTH_SHORT).show();
return true;
}
private void addnote () {
String description = Descriptionholder.getText().toString().trim();
if (!TextUtils.isEmpty(description)){
//generated unique number for id
String id = DatabaseNote.push().getKey();
PrivateNote pNote = new PrivateNote(id, description);
DatabaseNote.child(id).setValue(pNote); //pNote value added in id
Toast.makeText(this, "Note added", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(this, " Please Enter a note ", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onBackPressed() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Are you sure you want to exit?")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
FirebaseAuth.getInstance().signOut();
finish();
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
Adapter:
public class PrivateList extends ArrayAdapter<PrivateNote> {
private Activity context;
private List<PrivateNote> privateNoteList;
public PrivateList(Activity context, List<PrivateNote> privateNoteList){
super(context, R.layout.list_layout,privateNoteList);
this.context =context;
this.privateNoteList=privateNoteList;
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
LayoutInflater inflater = context.getLayoutInflater();
View listViewItem = inflater.inflate(R.layout.list_layout,null,true);
TextView textViewDescription = listViewItem.findViewById(R.id.TextViewDescription);
PrivateNote privateNote = privateNoteList.get(position);
textViewDescription.setText(privateNote.getNoteDescription());
return listViewItem;
}
}
PrivateNote:
public class PrivateNote {
public String noteId;
public String noteDescription;
public PrivateNote(){
}
PrivateNote(String noteId, String noteDescription){
this.noteId = noteId;
this.noteDescription=noteDescription;
}
String getNoteId()
{
return noteId;
}
String getNoteDescription()
{
return noteDescription;
}
}
In Firebase, there are two things,
FirebaseDatabase
FirebaseAuth
Usually, in almost all the apps, user data is stored in the FirebaseDatabase under the key, that is generated while creating a new user in your Firebase app.
So, for example, your database structure will look like this.
-Your_main_database
|____UserId_Of_FirebaseUser
|____stuff_related_to_user
|____More stuff related to user
So, you create a new user in FirebaseAuth, you can find more about it below:
Firebase Custom Auth.
Then, after creating a new user, you create child nodes under your database with the key=userId of your current logged in user.
eg. In your addNote function, the id variable will be equal to
String id = FirebaseAuth.getInstance().getCurrentUser().getUid();
Currently, you're using Push keys which are generated based on Timestamp, which you won't be able to associate with user unless you add a key inside your note object which stored current username, and then find all the child nodes that contain that username, but in that case, your data won't be organized at all.
Then, after you create a node with userId under your main database, you can then push new notes created by your user inside the userId with the push() function. So your database structure will look like below.
___
|
|__users
|__uniqueUserId
| |__note1
| |__note2
|__uniqueUserId2
|__note1
|__note2
|__note3
Next time whenever you want to fetch user created notes, you log in the user, get his ID, and then find the notes corresponding to that ID.
I don't see how you can fit SharedPreferences in there, before there is also function to cache data offline in Firebase once it is loaded.
Securing the notes:
If you implement the database like I said above, you'll be very easily able to secure your database.
Common Database Rules.
If you implement everything correctly like I told, you'll be able to secure your database with the fourth set of rules from above rules.
Since you are using firebase authentication, then you can retrieve the userId, and create the following database:
notes
userId
note : "todo"
description : "study"
Then you can do:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("notes");
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String userId = user.getUid();
ref.orderByKey().equalTo(userId).addValueEventListener(new ValueEventListener() {...}
This way you would retrieve the data of the currently logged in user only.
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
In the MainActivity I have both a ContextMenu that responds to Long clicks and a regular OnItemClickListener that responds to regular clicks.
On the TaskActivity which is practically similar to the MainActivity, I also have a ContextMenu that responds to Long clicks, however when trying to set an OnItemClickListener, the items in the list view don't respond (they do respond to long clicks).
What am I missing? I tried various methods like changing clickable status to false and so on - none of them work. And that makes sense because I don't have them on the MainActivity XML's but it does work there.
MainActivity code:
public class MainActivity extends AppCompatActivity {
final Context context = this;
public static final int SIGN_IN = 1;
public static String currentTaskListId;
public static String currentUserId;
private TaskListAdapter mTaskListAdapter;
//TextView that is displayed when the list is empty//
private TextView mEmptyStateTextView;
//The loading indicator //
private View loadingIndicator;
// Firebase instance variables
private FirebaseAuth mFirebaseAuth;
private FirebaseAuth.AuthStateListener mAuthStateListener;
private FirebaseDatabase mFirebaseDatabase;
private DatabaseReference mTaskListDatabaseReference;
private ChildEventListener mChildEventListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the content of the activity to use the activity_main.xml layout file - the task lists
setContentView(R.layout.activity_main);
// Initialize Firebase components
mFirebaseAuth = FirebaseAuth.getInstance();
mFirebaseDatabase = FirebaseDatabase.getInstance();
//Initialize firebase authentication
mAuthStateListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// user is signed in
currentUserId=user.getUid();
onSignedInInitialize(user.getUid());
} else {
// user is signed out
onSignedOutCleanup();
startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setIsSmartLockEnabled(false)
.setAvailableProviders(Arrays.asList(
new AuthUI.IdpConfig.EmailBuilder().build(),
new AuthUI.IdpConfig.GoogleBuilder().build()))
.setTosAndPrivacyPolicyUrls("https://superapp.example.com/terms-of-service.html",
"https://superapp.example.com/privacy-policy.html")
.build(),
SIGN_IN);
}
}
};
//Initialize task list Array, ListView and Adapter.
final ArrayList<TaskList> taskLists = new ArrayList<TaskList>();
// Create an {#link TaskListAdapter}, whose data source is a list of {#link TaskList}s.
mTaskListAdapter = new TaskListAdapter(this, taskLists);
// Locate the {#link ListView} object in the view hierarchy of the {#link Activity}.
ListView listView = (ListView) findViewById(R.id.task_list_view);
//Set the empty view
mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
listView.setEmptyView(mEmptyStateTextView);
//Initialize the loading indicator
loadingIndicator = findViewById(R.id.loading_indicator);
loadingIndicator.setVisibility(View.INVISIBLE);
// Make the {#link ListView} use the {#link TaskListAdapter} defined above, so that the
// {#link ListView} will display list items for each {#link TaskList} in the list.
listView.setAdapter(mTaskListAdapter);
//Set and create the FAB and it's action listener
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Get add_list.xml view
LayoutInflater li = LayoutInflater.from(context);
View addTaskListView = li.inflate(R.layout.add_list, null);
//Create the prompt to enable the user to create a new task list
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
context);
// Set add_list.xml as the layout for alertdialog builder
alertDialogBuilder.setView(addTaskListView);
//Set the user input box
final EditText userInput = (EditText) addTaskListView
.findViewById(R.id.edit_list_name);
// Set dialog message
alertDialogBuilder
.setCancelable(false)
.setPositiveButton("Create",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
// Get list title from user and create a new task list
//Also fetch the FireBase ID and connect it to the new task list.
String mTaskListId = mTaskListDatabaseReference.push().getKey();
TaskList taskList = new TaskList(userInput.getText().toString(),mTaskListId);
mTaskListDatabaseReference.child(mTaskListId).setValue(taskList);
}
})
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int id) {
dialog.cancel();
}
});
// Create the dialog
AlertDialog alertDialog = alertDialogBuilder.create();
// Show the dialog
alertDialog.show();
}
});
// Set an item click listener on the ListView, which creates an intent to open
//the relevant task list and show the tasks inside.
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
// Find the current task list that was clicked on
TaskList currentTaskList = mTaskListAdapter.getItem(position);
//get the current task list's ID
currentTaskListId=currentTaskList.getId();
// Create a new intent to view the tasks in the chosen list
Intent taskIntent = new Intent(MainActivity.this, TaskActivity.class);
// Send the intent to launch a new activity
startActivity(taskIntent);
}
});
listView.setLongClickable(true);
registerForContextMenu(listView);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SIGN_IN) {
if (resultCode == RESULT_OK) {
// Sign-in succeeded, set up the UI
Toast.makeText(this, "Signed in!", Toast.LENGTH_SHORT).show();
} else if (resultCode == RESULT_CANCELED) {
// Sign in was canceled by the user, finish the activity
Toast.makeText(this, "Sign in canceled", Toast.LENGTH_SHORT).show();
finish();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.mini_menu,menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.sign_out:
AuthUI.getInstance().signOut(this);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
protected void onResume() {
super.onResume();
mFirebaseAuth.addAuthStateListener(mAuthStateListener);
}
#Override
protected void onPause() {
super.onPause();
if (mAuthStateListener != null) {
mFirebaseAuth.removeAuthStateListener(mAuthStateListener);
}
mTaskListAdapter.clear();
detachDatabaseReadListener();
}
private void onSignedInInitialize(final String userId) {
//Get reference for the task list for the logged in user and attach the database listener
mTaskListDatabaseReference=mFirebaseDatabase.getReference().child("users").child(userId);
loadingIndicator.setVisibility(View.VISIBLE);
attachDatabaseReadListener();
mEmptyStateTextView.setText("No task lists, add a new one!");
loadingIndicator.setVisibility(View.GONE);
}
private void onSignedOutCleanup() {
mTaskListAdapter.clear();
detachDatabaseReadListener();
}
private void attachDatabaseReadListener() {
if (mChildEventListener == null) {
mChildEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
TaskList taskList = dataSnapshot.getValue(TaskList.class);
mTaskListAdapter.add(taskList);
}
public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
public void onChildRemoved(DataSnapshot dataSnapshot) {}
public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
public void onCancelled(DatabaseError databaseError) {}
};
}
mTaskListDatabaseReference.addChildEventListener(mChildEventListener);
}
private void detachDatabaseReadListener() {
if (mChildEventListener != null) {
mTaskListDatabaseReference.removeEventListener(mChildEventListener);
mChildEventListener = null;
}
}
public static String getCurrentTaskListId() {
return currentTaskListId;
}
public static String getCurrentUserId() {
return currentUserId;
}
/**
* MENU
*/
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo){
if (v.getId() == R.id.task_list_view){
AdapterView.AdapterContextMenuInfo info =(AdapterView.AdapterContextMenuInfo)menuInfo;
menu.add(0,0,0,"Delete");
}
}
#Override
public boolean onContextItemSelected(MenuItem menuItem){
AdapterView.AdapterContextMenuInfo info=(AdapterView.AdapterContextMenuInfo)menuItem.getMenuInfo();
TaskList taskListClicked=mTaskListAdapter.getItem(info.position);
Log.d("check","" +taskListClicked.getTitle());
switch (menuItem.getItemId()) {
case 0:
mTaskListDatabaseReference.child(taskListClicked.getId()).removeValue();
mTaskListAdapter.remove(taskListClicked);
Toast.makeText(this, "Task List deleted!", Toast.LENGTH_LONG).show();
break;
default:
break;
}
return true;
}
}
TaskActivity code:
public class TaskActivity extends AppCompatActivity {
final Context context = this;
private TaskAdapter mTaskAdapter;
private int taskCount;
// TextView that is displayed when the list is empty //
private TextView mEmptyStateTextView;
//The loading indicator //
private View loadingIndicator;
//Edit text and button for creating new tasks quickly
private EditText mTaskEditText;
private Button mTaskCreateButton;
// Firebase instance variables
private FirebaseDatabase mFirebaseDatabase;
private DatabaseReference mTaskDatabaseReference;
private DatabaseReference mTaskNumDatabaseReference;
private ChildEventListener mChildEventListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the content of the activity to use the activity_main.xml layout file - the task lists
setContentView(R.layout.task_activity);
//Set up to allow Up navigation to parent activity
this.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Initialize Firebase components
mFirebaseDatabase = FirebaseDatabase.getInstance();
// Initialize references to views
mTaskEditText = (EditText) findViewById(R.id.task_edit_text);
mTaskCreateButton = (Button) findViewById(R.id.create_task_button);
// Enable Send button when there's text to send
mTaskEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (charSequence.toString().trim().length() > 0) {
mTaskCreateButton.setEnabled(true);
} else {
mTaskCreateButton.setEnabled(false);
}
}
#Override
public void afterTextChanged(Editable editable) {
}
});
// Create button creates a new task and clears the EditText
mTaskCreateButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Get task title from user and create a new task
//Also fetch the FireBase ID and connect it to the new task.
//And finally get the task's creation date
String creationDate ="Created: " + new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());
String taskId = mTaskDatabaseReference.push().getKey();
Task task = new Task(mTaskEditText.getText().toString(),false,taskId,creationDate);
mTaskDatabaseReference.child(taskId).setValue(task);
//add that task to the list's task count
mTaskNumDatabaseReference.child("taskNum").setValue(taskCount+1);
// Clear input box
mTaskEditText.setText("");
}
});
//Initialize task Array, ListView and Adapter.
final ArrayList<Task> tasks = new ArrayList<Task>();
// Create an {#link TaskAdapter}, whose data source is a list of {#link Task}s.
mTaskAdapter = new TaskAdapter(this, tasks);
// Locate the {#link ListView} object in the view hierarchy of the {#link Activity}.
ListView listView = (ListView) findViewById(R.id.task_list_view);
//Set the empty view
mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
listView.setEmptyView(mEmptyStateTextView);
//Initialize the loading indicator
loadingIndicator = findViewById(R.id.loading_indicator);
loadingIndicator.setVisibility(View.INVISIBLE);
// Make the {#link ListView} use the {#link TaskAdapter} defined above, so that the
// {#link ListView} will display list items for each {#link Task} in the list.
listView.setAdapter(mTaskAdapter);
//Set a regular click - opening the TaskInfoFragment
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
// Find the current task list that was clicked on
Log.d("clicked here bro","clicikcckckc");
Task currentTask = mTaskAdapter.getItem(position);
//Open the TaskInfoFragment for this task
TaskInfoFragment taskInfo = new TaskInfoFragment();
taskInfo.setCurrentTask(currentTask);
android.support.v4.app.FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.frag_container, taskInfo);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
});
//Set context menu for ListView
listView.setLongClickable(true);
registerForContextMenu(listView);
//Get reference for the task list for the logged in user and attach the database listener
mTaskDatabaseReference=mFirebaseDatabase.getReference().child("users")
.child(MainActivity.getCurrentUserId())
.child(MainActivity.getCurrentTaskListId()).child("tasks");
mTaskNumDatabaseReference=mFirebaseDatabase.getReference().child("users")
.child(MainActivity.getCurrentUserId())
.child(MainActivity.getCurrentTaskListId());
//add listener to get the current task count in this specific task list
mTaskNumDatabaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
TaskList taskList = dataSnapshot.getValue(TaskList.class);
taskCount=taskList.getTaskNum();
Log.d("post count: ", "" + taskCount);
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getCode());
}
});
}
#Override
protected void onResume() {
super.onResume();
loadingIndicator.setVisibility(View.VISIBLE);
attachDatabaseReadListener();
mEmptyStateTextView.setText("No tasks, add a new one!");
loadingIndicator.setVisibility(View.GONE);
}
#Override
protected void onPause() {
super.onPause();
mTaskAdapter.clear();
detachDatabaseReadListener();
}
private void attachDatabaseReadListener() {
if (mChildEventListener == null) {
mChildEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Task task = dataSnapshot.getValue(Task.class);
mTaskAdapter.add(task);
}
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
//Task task = dataSnapshot.getValue(Task.class);
//mTaskAdapter.add(task);
}
public void onChildRemoved(DataSnapshot dataSnapshot) {
mTaskNumDatabaseReference.child("taskNum").setValue(taskCount-1);
}
public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
public void onCancelled(DatabaseError databaseError) {}
};
}
mTaskDatabaseReference.addChildEventListener(mChildEventListener);
}
private void detachDatabaseReadListener() {
if (mChildEventListener != null) {
mTaskDatabaseReference.removeEventListener(mChildEventListener);
mChildEventListener = null;
}
}
/**
* MENU
*/
#Override
public void onCreateContextMenu(ContextMenu menu,View v, ContextMenu.ContextMenuInfo menuInfo){
if (v.getId() == R.id.task_list_view){
AdapterView.AdapterContextMenuInfo info =(AdapterView.AdapterContextMenuInfo)menuInfo;
menu.add(0,0,0,"Delete");
menu.add(0,1,1,"info");
}
}
#Override
public boolean onContextItemSelected(MenuItem menuItem){
AdapterView.AdapterContextMenuInfo info=(AdapterView.AdapterContextMenuInfo)menuItem.getMenuInfo();
Task taskClicked=mTaskAdapter.getItem(info.position);
Log.d("check","" +taskClicked.getTitle());
switch (menuItem.getItemId()) {
case 0:
mTaskDatabaseReference.child(taskClicked.getId()).removeValue();
mTaskAdapter.remove(taskClicked);
Toast.makeText(this, "Task deleted!", Toast.LENGTH_LONG).show();
break;
case 1:
//Open the TaskInfoFragment for this task
TaskInfoFragment taskInfo = new TaskInfoFragment();
taskInfo.setCurrentTask(taskClicked);
android.support.v4.app.FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.frag_container, taskInfo);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
break;
default:
break;
}
return true;
}
//set up the back button - to navigate to the parent activity
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
// Respond to the action bar's Up/Home button
case android.R.id.home:
//Check if the call came from the TaskInfoFragment or the activity
Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.frag_container);
if(currentFragment!=null && currentFragment.isVisible()){
this.onBackPressed();
}
else{
NavUtils.navigateUpFromSameTask(this);
}
return true;
}
return super.onOptionsItemSelected(item);
}
}
TaskAdapter - the TaskActivity Adapter
package com.example.guyerez.todotiger;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.TextView;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import java.util.ArrayList;
import java.util.Locale;
/**
* {#link TaskAdapter} is an {#link ArrayAdapter} that can provide the layout for each task item
* based on a data source, which is a list of {#link Task} objects.
*/
public class TaskAdapter extends ArrayAdapter<Task> {
//Define FireBase instance variables
private DatabaseReference mTaskDatabaseReference;
private FirebaseDatabase mFirebaseDatabase;
/**
* Create a new {#link TaskAdapter} object.
*
* #param context is the current context (i.e. Activity) that the adapter is being created in.
* #param tasks is the list of {#link Task}s to be displayed.
*/
public TaskAdapter(Context context, ArrayList<Task> tasks) {
super(context, 0, tasks);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Check if an existing view is being reused, otherwise inflate the view
View listItemView = convertView;
if (listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(
R.layout.task_item, parent, false);
}
// Get the {#link Task} object located at this position in the list
final Task currentTask = getItem(position);
// Locate the TextView in the task_item.xml layout with the ID task_title.
final TextView titleTextView = (TextView) listItemView.findViewById(R.id.task_title);
// Get the task's title from the currentTask object and set it in the text view
titleTextView.setText(currentTask.getTitle());
//If the task is completed - title Strikethrough
titleTextView.setBackgroundResource(strikeCompleted(currentTask.getCompleted()));
//Initialize the check box and check it if the task was completed.
CheckBox checkBox = (CheckBox) listItemView.findViewById(R.id.check_box);
checkBox.setOnCheckedChangeListener(null);
checkBox.setChecked(currentTask.getCompleted());
//Initialize the creation date TextView in the task_item.xml layout with the ID creation_date
TextView creationDateTextView = (TextView) listItemView.findViewById(R.id.creation_date);
//Get the task's creation date from the currentTask object and set it in the text view
creationDateTextView.setText(currentTask.getCreationDate());
// Initialize Firebase DB
mFirebaseDatabase = FirebaseDatabase.getInstance();
//Get the task DB reference to edit task completion status
// Find the CheckBox in the task_item.xml layout with the ID check_box.
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
mTaskDatabaseReference=mFirebaseDatabase.getReference()
.child("users").child(MainActivity.getCurrentUserId())
.child(MainActivity.getCurrentTaskListId()).child("tasks").child(currentTask.getId());
if (isChecked) {
titleTextView.setBackgroundResource(R.drawable.strike_through);
mTaskDatabaseReference.child("completed").setValue(true);
} else {
titleTextView.setBackgroundResource(0);
mTaskDatabaseReference.child("completed").setValue(false);
}
}
}
);
// Return the whole list item layout (containing 1 text view and 1 checkbox) so that it can be shown in the ListView.
return listItemView;
}
private int strikeCompleted(boolean completed){
if (completed){
return R.drawable.strike_through;
}
else{
return 0;
}
}
}
After trying the several recommended workarounds (like here) for ListView rows containing a CheckBox without any success, I'd like to suggest a different approach:
Use another, transparent View which covers the whole row except for a small area around the CheckBox. Let this View have an OnClickListener which triggers the opening of the TaskInfoFragment.
Ideally one would use an interface so the TaskAdapter could pass the clicked Task to the TaskActivity which in turn would show the Fragment.
Several hours later... (#Guy, your hint that you "tried deleting all checkbox related code and xml, and the regular click problem persisted" made me exchange one component after another until I had it narrowed down to the row xml) I found the reason why the ListView's OnItemClickListener in TaskActivity does not fire. The root ConstraintLayout of the Task list has an attribute which the root of the TaskList list does not have: android:longClickable="true"
Removing this attribute makes the ListView behave normally.
I am fairly new in android programming.
I am having two cases where I am unable to get the list updated.
FIRST
Here is my Activity (QuestionList Activity).
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ques_list);
....
quesList=quesDB.getQues(); //getting arraylist from database
qAdapter = new QuesList_Adaptor(quesList, this, this);
rv_qlist.setAdapter(qAdapter);
qAdapter.notifyDataSetChanged();
}
On other activity, taking user input which updates the database (thus also updates quesList above).
public void save (View view)
{
String ques = et_ques.getText().toString();
String optionA = et_optA.getText().toString();
String optionB = et_optB.getText().toString();
String optionC = et_optC.getText().toString();
String optionD = et_optD.getText().toString();
String ans = et_ans.getText().toString();
QuesDB qd = new QuesDB(this);
boolean b = qd.addQues(ques, optionA, optionB, optionC, optionD, ans);
if (b)
{
Toast.makeText(this, "Question Saved", Toast.LENGTH_SHORT).show();
}
*//so... I have to notify adapter here right? than, what's the way here to reference adaptor and use notifyDataSetChanged*
finish();
SECOND CASE
Setting up Multi-delete on recyclerview. Data is getting deleted but trouble in refreshing the list.
Please take a look into the code, I mentioned there using comments.
On Activity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
..
StoreNotesDB sdb = new StoreNotesDB(this);
noteslist= sdb.getStoreNotes(); //storing from database to array
mAdapter = new AdaptorNotes(this,noteslist, this);
rv.setAdapter(mAdapter);
}
#Override
public void OnLongClick() {
fab.setVisibility(View.GONE);
inActionMode = true;
actionMode = this.startActionMode(new ContextualCallback());
mAdapter.notifyDataSetChanged();
}
#Override
public void OnClick(AdaptorNotes.MyViewHolder holder, int pos) {
if (holder.chk_notes.isChecked())
{
selected_list.add(noteslist.get(pos));
//counter = counter + 1;
}
else
{
selected_list.remove(noteslist.get(pos));
//counter = counter - 1;
}
}
class ContextualCallback implements ActionMode.Callback {
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
actionMode.getMenuInflater().inflate(R.menu.notescontextual_menu, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem item) {
switch (item.getItemId()) {
case R.id.action_delete:
//Toast.makeText(MainActivity.this,"delete",Toast.LENGTH_SHORT).show();
if (selected_list.isEmpty()) {
Toast.makeText(NotesListViewActivity.this, "No item is selected", Toast.LENGTH_SHORT).show();
}
else{
//loop for deleting item from database of the selected list
for (MyStoreNotes myStoreNotes: selected_list)
{
String x = String.valueOf(myStoreNotes.getSl());
int y = storeNotesDB.deleteRow(x);
}
mAdapter.notifyDataSetChanged(); // it doesn't work
inActionMode = false;
selected_list.clear();
Toast.makeText(NotesListViewActivity.this, "Selected List Deleted", Toast.LENGTH_SHORT).show();
actionMode.finish();
}
}
return false;
}......
.....
I'm not sure if you're trying to refresh the data on each load of the activity, or if you are using a different method to refresh your data.
If you want to reload the data each time the recyclerview activity is shown, then you need to call...
quesList.clear();
after declaring the list, and before getting the data. That ensures that you are populating your recyclerview with the latest data from your database.
If this is not what you're asking, please explain what your app is currently doing vs what you want it to do.
I'm stuck for few days, and unfortunately dont know how to fix it.
I have DetailScreen.java that show data from MainScreen (one of recyclerview's list).
I tried this code but there is no effect, when i try to change use
COLUMN_NOMOR in my update function, i can change the name but
getting error when change the nomor. I guess, its right to use
COLUMN_ID in my update function because id is my PK-AI. So whether
because I didnt call COLUMN_ID in my DetailScreen? But how i can call my
id in my DetailsScreen also in my UpdateScreen?
If the data success updated, the screen will be automatically go to the DetailScreen again, but still showing old data. I had to go to MainActivity first to get the new data. Where code should i modified?
Here my Update function in my DBHandler.java
public int updateDataSiswa(Siswa siswa) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_NOMOR, siswa.getNomor());
values.put(COLUMN_NAMA, siswa.getNama());
return db.update(TABLE_SISWA, values, COLUMN_ID + " = ?",
new String[]{String.valueOf(siswa.getId())});
}
Here DetailScreen.java
public class DetailScreen extends AppCompatActivity {
private TextView txt_resultnomor, txt_resultnama;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.screen_details);
//put data
Intent i = getIntent();
final String id = i.getExtras().getString("id");
final String nomor = i.getExtras().getString("nomor");
final String nama = i.getExtras().getString("nama");
//inisialisasi
txt_resultnomor = (TextView) findViewById(R.id.txt_resultnomor);
txt_resultnama = (TextView) findViewById(R.id.txt_resultnama);
//set
txt_resultnomor.setText(nomor);
txt_resultnama.setText(nama);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_detail, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_edit) {
Intent in = new Intent(this, UpdateScreen.class);
in.putExtra("nomor", txt_resultnomor.getText().toString());
in.putExtra("nama", txt_resultnama.getText().toString());
startActivity(in);
}
if (id == R.id.action_delete) {
return true;
}
if (id == R.id.action_settings) {
// Intent i = new Intent(this, About.class);
//startActivity(i);
}
return super.onOptionsItemSelected(item);
}
}
Then here my UpdateScreen.java
public class UpdateScreen extends AppCompatActivity {
private EditText et_nomor;
private EditText et_nama;
private Button button_updatedata;
private DBHandler dbHandler;
private SiswaAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update_screen);
dbHandler = new DBHandler(this);
initComponents();
}
private void initComponents(){
et_nomor = (EditText) findViewById(R.id.et_nomor);
et_nama = (EditText) findViewById(R.id.et_nama);
//ambil data
Intent in=getIntent();
final String id=in.getExtras().getString("id_siswa");
final String nomor=in.getExtras().getString("nomor");
final String nama=in.getExtras().getString("nama");
//set inisial
et_nomor.setText(nomor);
et_nama.setText(nama);
button_updatedata = (Button) findViewById(R.id.button_updatedata);
button_updatedata.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
validasiForm();
}
});
}
private void validasiForm() {
String form_nomor = et_nomor.getText().toString();
String form_nama = et_nama.getText().toString();
if (form_nomor.isEmpty()){
et_nomor.setError("Nomor belum diisi");
et_nomor.requestFocus();
}
else if (form_nama.isEmpty()){
et_nama.setError("Nama belum diisi");
et_nama.requestFocus();
}
else {
dbHandler.updateDataSiswa(new Siswa(form_nomor, form_nama));
List<Siswa> siswaList = dbHandler.getSemuaSiswa();
adapter = new SiswaAdapter(siswaList);
adapter.notifyDataSetChanged();
Toast.makeText(UpdateScreen.this, "Berhasil Memperbarui Data Siswa", Toast.LENGTH_SHORT).show();
MainSiswaActivity.mma.refresh();
finish();
}
}
}
I hope i tell clearly, help me please. Thanks.
where is your call to the update method you given public int updateDataSiswa(Siswa siswa)..? Also based on what you have provided...your notifyDataSetChanged() for adapter just tries to update the listview of the RecyclerView..
but it does not understand what underlying data has changed for it..you need to create a method for your Database Handler where you can fetch a List of new records..and then use this method to update your adapter with it and then set the new adapter to your listView in validasiForm() method..
please check this for more details...Android ListView not refreshing after notifyDataSetChanged