Problem: In this code when I press the button it should add a new flashcard cardview, that is binded to an arraylist, it does that for the first few times but after a few times, the data written first in the arraylist becomes empty and instead of adding one card, it adds more then 1 till it gets to the size+1 -I understand that the second problem is a direct consequence of the first problem-, instead I want it to just add the new flashcard to the bottom of the arraylist without deleting any of the data before it
the code:
case R.id.add_button:
String previousTitle = titletxt;
titletxt = Title.getText().toString();
descriptiontxt = Description.getText().toString();
if (titletxt.trim().isEmpty()) {
// Show pop up message to put in a title
Toast.makeText(this, "Please enter a title", Toast.LENGTH_SHORT).show();
break;
}
if (!titletxt.equals(previousTitle)) {
// Delete the old reference
db.collection("FlashcardSets")
.document("flashcards" + userID + previousTitle)
.delete()
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d("Firestore", "Document successfully deleted!");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w("Firestore", "Error deleting document", e);
}
});
}
if (dataList.size() > 0) {
for (int i = 0; i < dataList.size(); i++) {
flashCardMake data = dataList.get(i);
String title = "flashcard" + (i + 1);
Map<String, Object> flashcard = new HashMap<>();
flashcard.put("term", data.getTerm());
flashcard.put("definition", data.getDefinition());
db.collection("FlashcardSets")
.document("flashcards" + userID + titletxt)
.collection("flashcards")
.document(title)
.set(flashcard)
.addOnSuccessListener(new OnSuccessListener() {
#Override
public void onSuccess(Object o) {
Log.d("Firestore", "DocumentSnapshot successfully written!");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w("Firestore", "Error writing document", e);
}
});
}
}
Map<String, Object> flashcardData = new HashMap<>();
flashcardData.put("title", titletxt);
flashcardData.put("description", descriptiontxt);
db.collection("FlashcardSets")
.document("flashcards" + userID + titletxt + ".txt")
.set(flashcardData)
.addOnSuccessListener(new OnSuccessListener() {
#Override
public void onSuccess(Object o) {
Log.d("Firestore", "DocumentSnapshot successfully written!");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w("Firestore", "Error writing document", e);
}
});
if(!(dataList.isEmpty())){
Toast.makeText(this, dataList.get(0).getTerm().toString(), Toast.LENGTH_SHORT).show();}
flashCardMake data = new flashCardMake();
dataList.add(data);
adapter.notifyDataSetChanged();
recyclerView.scrollToPosition(0);
break;
and the Adapter's code is this:
import android.content.Context;
import android.support.annotation.NonNull;
import android.text.Editable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class flashcardMakeAdapter extends RecyclerView.Adapter<flashcardMakeAdapter.ViewHolder> {
private ArrayList<flashCardMake> dataList;
private Context context;
public flashcardMakeAdapter(Context context,ArrayList<flashCardMake> dataList) {
this.dataList = dataList;
this.context=context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.flashcard_add, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
flashCardMake data = dataList.get(position);
// bind the data to the card view here
data.setDefinition(holder.definition.getText().toString());
data.setTerm(holder.term.getText().toString());
}
#Override
public int getItemCount() {
return dataList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
// define the views in the card view here
EditText term, definition;
public ViewHolder(#NonNull View itemView) {
super(itemView);
term=itemView.findViewById(R.id.term);
definition=itemView.findViewById(R.id.definition);
// find the views by id here
}
}
}
I was trying to make it that every time the add button is pressed it adds a flashcard as well as updating the list of flashcard in the database, but what's happening is that after multiple cards have been put the data that's put in the first one or few position gets deleted, for example if we say the data in the arraylist is like this [1,2,3,4,5,6,7]--I press the button-->[2,3,4,5,6,7, , ]--I press the button again--> [4,5,6,7, , , , , ]
Related
I implemented searchView in android which filters data. It works correctly But after filtering data, when I add new data it does not show in recyclerView when I restart the app then it shows, I am also able to view that item after again searching something and then backspace it.
Here is My Adapter Class
package com.example.keepnotes;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
Context context;
ArrayList<Notes> arrNotes;
DatabaseHelper databaseHelper;
RecyclerViewAdapter(Context context, ArrayList<Notes> arrNotes, DatabaseHelper databaseHelper) {
this.context = context;
this.arrNotes = arrNotes;
this.databaseHelper = databaseHelper;
}
public void setFilteredList(ArrayList<Notes> filteredList) {
this.arrNotes = filteredList;
notifyDataSetChanged();
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.single_view, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, #SuppressLint("RecyclerView") int position) {
holder.title.setText(arrNotes.get(position).title);
holder.body.setText(arrNotes.get(position).text);
holder.index.setText(String.valueOf(position + 1));
holder.llView.setOnClickListener(view -> {
Intent iNext = new Intent(context, ViewActivity.class);
iNext.putExtra("title", arrNotes.get(position).title);
iNext.putExtra("text", arrNotes.get(position).text);
iNext.putExtra("id", arrNotes.get(position).id);
context.startActivity(iNext);
});
holder.llView.setOnLongClickListener(view -> {
showDeleteDialog(position);
return true;
});
}
#Override
public int getItemCount() {
return arrNotes.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView title, body, index;
CardView llView;
public ViewHolder(View itemView) {
super(itemView);
title = itemView.findViewById(R.id.text_title_view);
body = itemView.findViewById(R.id.text_text_view);
index = itemView.findViewById(R.id.index);
llView = itemView.findViewById(R.id.card_View);
databaseHelper = DatabaseHelper.getDatabase(context);
}
}
private void showDeleteDialog(int position) {
AlertDialog.Builder alert = new AlertDialog.Builder(context)
.setTitle("Delete view")
.setMessage("Are you sure to delete")
.setIcon(R.drawable.ic_baseline_delete_24)
.setPositiveButton("yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
databaseHelper.notesDao().deleteNotes(new Notes(arrNotes.get(position).getId(), arrNotes.get(position).getTitle(), arrNotes.get(position).getText()));
}
})
.setNegativeButton("No", (dialogInterface, i) -> {
});
alert.show();
}
}
Here is My filterable function
private void filterList(String text) {
ArrayList<Notes> filteredList = new ArrayList<>();
for (Notes notes : arrNotes) {
if (notes.title.toLowerCase().contains(text.toLowerCase()) || notes.text.toLowerCase().contains(text.toLowerCase())) {
filteredList.add(notes);
}
if (!(filteredList.isEmpty())) {
adapter.setFilteredList(filteredList);
}
}
}
Here I implemented SearchView
searchView = findViewById(R.id.searchView);
searchView.clearFocus();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
filterList(newText);
return false;
}
});
I updated data using live data using this
modelView = new ViewModelProvider(this).get(notesModelView.class);
modelView.getAllNotes().observe(this, new Observer<List<Notes>>() {
#Override
public void onChanged(List<Notes> notes) {
arrNotes.clear();
arrNotes.addAll(notes);
adapter.notifyDataSetChanged();
}
});
Modify your filterList() function like this -
private void filterList(String text) {
if (!text.trim().isEmpty()) {
ArrayList<Notes> filteredList = new ArrayList<>();
for (Notes notes : arrNotes) {
if (notes.title.toLowerCase().contains(text.toLowerCase()) || notes.text.toLowerCase().contains(text.toLowerCase())) {
filteredList.add(notes);
}
adapter.setFilteredList(filteredList);
}
}else{
adapter.setFilteredList(arrNotes);
}
}
I am working on an Android app with a steadily growing Code basis; the aim of the app is to scan and process QR Codes and Barcodes on Handheld Devices for Storages (not Smartphones). It hast two Activities that contain major parts of the programmatical logic; hence, I want to store major parts of the Code that contains the Functionality for processing the Scanner input in an external Service, called Scanner Service, implement the methods there and use the methods in other Activites;
however, I have a major issue with the use of Context, getApplicationContext() and the reference of the Activity in the Service and vice versa; although I think I have referenced and initialised the Textviews from the Activity in the Service, the app keeps on crashing with the following error message:
AndroidRuntime: Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.app.Activity.findViewById(int)' on a null object reference
at com.xxxx.ScanService.<clinit>(ScanService.java:16)
I know what it means, but I donĀ“t know how I could access the View
private static TextView content = (TextView) a.findViewById(R.id.content_detail);
in such a way that I can use it in the Service and in the Activity and the app stops crashing.
Therefore, any hints or help would be very much appreciated, thank you in advance.
The MainDetailActivity:
package com.example.xxx_app;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.RecyclerView;
import android.view.MenuItem;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.PopupMenu;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import static com.xxx.ScanService.*;
import static com.xxx.SimpleItemRecyclerViewAdapter.TAGG;
/**
* An activity representing a single Main detail screen. This
* activity is only used on narrow width devices. On tablet-size devices,
* item details are presented side-by-side with a list of items
* in a {#link MainListActivity}.
*/
public class MainDetailActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener,
PopupMenu.OnMenuItemClickListener {
Context context;
private RecyclerView recyclerView;
private RecyclerviewAdapter recyclerviewAdapter;
private RecyclerTouchListener touchListener;
private ListView listView;
public TextView textView4;
public String code;
public static final String TAG = "Barcode ist:" ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_detail);
context = this;
//TextView headerView = findViewById(R.id.txt1);
Spinner spinner = (Spinner) findViewById(R.id.spinner);
EditText editBarcode = (EditText) findViewById(R.id.editText);
TextView content = (TextView) findViewById(R.id.content_detail);
TextView editTextNumber = findViewById(R.id.editTextNumber);
Button addBooking = findViewById(R.id.button);
Button removeBooking = findViewById(R.id.button2);
removeBooking.setEnabled(false);
spinner.setOnItemSelectedListener(this);
//String selectedItem = spinner.getSelectedItem().toString();
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.mockdata, android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner.setAdapter(adapter);
String scannedCode = getIntent().getStringExtra("scannedCode");
Log.d(TAG, "scannedCode" + scannedCode);
if (scannedCode != null && (content.getText().toString().equals(""))) {
content.setText(scannedCode);
}
Button btn = findViewById(R.id.imageView4);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PopupMenu popup = new PopupMenu(MainDetailActivity.this, v);
popup.setOnMenuItemClickListener(MainDetailActivity.this);
popup.inflate(R.menu.popup_menu);
popup.show();
}
});
editBarcode.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
String code = editBarcode.getText().toString();
if (code.matches("")) //{ if(code.trim().isEmpty())
//|| editBarcode.getText().toString() > 100 )
{
Log.d(TAG, "Code ist leer");
}
if (keyCode == KeyEvent.KEYCODE_ENTER && code.length() > 0) {
editBarcode.setText("");
ScanService.checkEnteredCode(code);
return true;
}
return false;
}
});
recyclerView = findViewById(R.id.recyclerview);
recyclerviewAdapter = new RecyclerviewAdapter(this);
Intent newIntent = getIntent();
String receivedPalNo = newIntent.getStringExtra("palNo");
String receivedNo = newIntent.getStringExtra("no");
String receivedType = newIntent.getStringExtra("type");
String receivedRack = newIntent.getStringExtra("rack");
String receivedCountItems = newIntent.getStringExtra("count_items");
content.setText(receivedCountItems);
RestClient.getPaletteItems(getApplicationContext(),recyclerviewAdapter,receivedPalNo);
Log.d(TAGG,"Intent 1" + receivedPalNo);
Log.d(TAGG, "Intent 2" + receivedNo);
Log.d(TAGG, "Intent 3" + receivedType);
Log.d(TAGG,"Intent 4" + receivedRack);
Log.d(TAGG, "Intent 5" + receivedCountItems);
final ArrayList<Items> itemList = new ArrayList<>();
/*
Items[] items = new Items(12345,123456, 200, 500);
itemList.add(items);*/
recyclerviewAdapter.setItemList((ArrayList<Items>) itemList);
recyclerView.setAdapter(recyclerviewAdapter);
touchListener = new RecyclerTouchListener(this,recyclerView);
RecyclerviewAdapter finalRecyclerviewAdapter = recyclerviewAdapter;
touchListener
.setClickable(new RecyclerTouchListener.OnRowClickListener() {
#Override
public void onRowClicked(int position) {
//Toast.makeText(getApplicationContext(),itemList.get(position), Toast.LENGTH_SHORT).show();
}
#Override
public void onIndependentViewClicked(int independentViewID, int position) {
}
})
.setSwipeOptionViews(R.id.delete_task,R.id.edit_task)
.setSwipeable(R.id.rowFG, R.id.rowBG, new RecyclerTouchListener.OnSwipeOptionsClickListener() {
#Override
public void onSwipeOptionClicked(int viewID, int position) {
switch (viewID){
case R.id.delete_task:
itemList.remove(position);
finalRecyclerviewAdapter.setItemList(itemList);
break;
case R.id.edit_task:
Toast.makeText(getApplicationContext(),"Edit Not Available",Toast.LENGTH_SHORT).show();
break;
}
}
});
recyclerView.addOnItemTouchListener(touchListener);
class StableArrayAdapter extends ArrayAdapter<String> {
HashMap<String, Integer> mIdMap = new HashMap<String, Integer>();
public StableArrayAdapter(Context context, int textViewResourceId,
List<String> objects) {
super(context, textViewResourceId, objects);
for (int i = 0; i < objects.size(); ++i) {
mIdMap.put(objects.get(i), i);
}
}
#Override
public long getItemId(int position) {
String item = getItem(position);
return mIdMap.get(item);
}
#Override
public boolean hasStableIds() {
return true;
}
}
// savedInstanceState is non-null when there is fragment state
// saved from previous configurations of this activity
// (e.g. when rotating the screen from portrait to landscape).
// In this case, the fragment will automatically be re-added
// to its container so we don"t need to manually add it.
// For more information, see the Fragments API guide at:
//
// http://developer.android.com/guide/components/fragments.html
//
String text = getIntent().getStringExtra("palNo");
//headerView.setText(text);
if (receivedType != null && receivedType.equals("FE")) {
ImageView mImgView = findViewById(R.id.id_col_code);
mImgView.setBackgroundResource(R.drawable.backgroun_blue);
}
if (receivedType != null && receivedType.equals("UFE")) {
ImageView mImgView = findViewById(R.id.id_col_code);
mImgView.setBackgroundResource(R.drawable.backgroun_yellow);
}
}
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public boolean onMenuItemClick(MenuItem item) {
Toast.makeText(this, "Selected Item: " +item.getTitle(), Toast.LENGTH_SHORT).show();
switch (item.getItemId()) {
case R.id.search_item:
// do your code
return true;
case R.id.upload_item:
// do your code
return true;
case R.id.copy_item:
// do your code
return true;
/* case R.id.print_item:
// do your code
return true;*/
case R.id.share_item:
// do your code
return true;
/*case R.id.bookmark_item:
// do your code
return true;*/
default:
return false;
}
}
public void newDialog(Activity activity) {
final Dialog dialog = new Dialog(activity);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCancelable(true);
dialog.setContentView(R.layout.sortiment_layout);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
Button okButton = dialog.findViewById(R.id.ok);
okButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Toast.makeText(getApplicationContext(),"Ok" ,Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});
Button cancelButton = dialog.findViewById(R.id.cancel);
cancelButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Toast.makeText(getApplicationContext(),"Abbrechen" ,Toast.LENGTH_SHORT).show();
dialog.cancel();
}
});
dialog.show();
}
public void showDialog(Activity activity) {
final Dialog dialog = new Dialog(activity);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCancelable(true);
dialog.setContentView(R.layout.newcustom_layout);
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
Button okButton = dialog.findViewById(R.id.ok);
okButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Toast.makeText(getApplicationContext(),"Ok" ,Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});
dialog.show();
}
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
// An item was selected. You can retrieve the selected item using
// parent.getItemAtPosition(pos)
}
public void onNothingSelected(AdapterView<?> parent) {
// Another interface callback
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
// This ID represents the Home or Up button. In the case of this
// activity, the Up button is shown. For
// more details, see the Navigation pattern on Android Design:
//
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
//
navigateUpTo(new Intent(this, MainListActivity.class));
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onResume() {
super.onResume();
recyclerView.addOnItemTouchListener(touchListener);
}
#Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
}
The ScanService Class:
package com.example.xxx;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.widget.TextView;
public class ScanService {
private static final String TAG = "Scan Service Tag";
private static Context mContext;
private static Activity a = (MainDetailActivity)mContext;
private static TextView content = (TextView)
a.findViewById(R.id.content_detail);
private static TextView editTextNumber = (TextView)
a.findViewById(R.id.editTextNumber);
public ScanService (Context mContext) {
this.mContext = mContext;
}
public static void checkEnteredCode(String code, Activity a) {
content.setText("");
//PSP-H1-EA-F3
if
(code.matches("PSP-\\p{Upper}\\d\\p{Punct}\\p{Upper}\\" +
"p{Upper}\\p{Punct}\\p{Upper}\\p{Digit}")) {
content.setText("");
content.setText(code);
Log.d(TAG, "xxx");
}
if (code.matches("LF-[0-9]*")) {
///LF-(\d+)/gi
content.setText("");
content.setText(code);
Log.d(TAG, "xxx");
}
if (code.matches("PAL-[0-9][0-9][0-9]")) {
content.setText("");
content.setText(code);
Log.d(TAG, "xxx");
}
if (code.matches("P-[0-9][0-9][0-9]")) {
content.setText("");
content.setText(code);
Log.d(TAG, "Palette");
}
if (code.matches("[0-9][0-9][0-9][0-9].[0-9][0-9].+DB")) {
if(editTextNumber == null) {
Log.d(TAG, "xxx");
}
else {
editTextNumber.setText(code);
Log.d(TAG, "xxx");
}
Log.d(TAG, "xxx");
}
if (code.matches("[0-9A-Z]*[0-9]*")) {
//editBarcode.setText("");
//editBarcode.setText(keyCode);
Log.d(TAG, "xxx");
}
if (code.matches("\\d{13}")) {
//newDialog(MainDetailActivity.this);
//editBarcode.setText("");
//editBarcode.setText(keyCode);
if(editTextNumber == null) {
Log.d(TAG, "xxx");
}
else {
editTextNumber.setText(code);
Log.d(TAG, "xxx");
}
Log.d(TAG, "xxx");
}
else {
Log.d(TAG, "xxx");
};
//editBarcode.setText("");
//editBarcode.setText(code);
/* String code = editBarcode.getText().toString();
if (code.matches("")) //{ if(code.trim().isEmpty())
//|| editBarcode.getText().toString() > 100 )
{
Log.d(TAG, "xxx");
}
//}
checkEnteredCode(code);
//editBarcode.setText("");
return Boolean.parseBoolean(code);*/
Log.d(TAG, code);
}
public static void checkEnteredCode(String code) {
}
}
You cannot access any Views from a Service! Views belong to the Activity. This is the wrong application architecture. A Service performs background processing (file I/O, network I/O, computation, etc.). The Activity is responsible for interacting with the user (inputs, display, etc.). If your Service wants to put data on the screen, you've broken the division of responsibilities. Your Service should simply notify your Activity (or any other component that is interested) when data has changed, and the Activity can then update the View itself. You can share data between the Service and your other components in a number of ways, including: event bus, publish/subscribe, shared preferences, broadcast Intents, SQLite database, etc.
I used an alert dialog box for confirmation of delete, I make a recycler view in which two methods are applied 1.swipe for delete method, 2. menu bar delete method. In swipe method when I swipe the view it removed the list and show alert dialog when clicking no then it replaces not original space but another space that creates a space between them kindly guide me what issue it is?
package com.example.framelayout;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.snackbar.BaseTransientBottomBar;
import com.google.android.material.snackbar.Snackbar;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MainActivity extends AppCompatActivity implements RecyclerClickListener, RecyclerActionClick {
private RecyclerView recyclerView;
private detailAdapt adapt;
private List<detailModel> modelList = new ArrayList<>();
detailModel modelData, swipeData;
ItemTouchHelper.SimpleCallback simpleCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
#Override
public boolean onMove(#NonNull RecyclerView recyclerView, #NonNull RecyclerView.ViewHolder viewHolder, #NonNull RecyclerView.ViewHolder target) {
return false;
}
#Override
public void onSwiped(#NonNull RecyclerView.ViewHolder viewHolder, int direction) {
final int position = viewHolder.getAdapterPosition();
if (direction == ItemTouchHelper.LEFT) {
swipeData = modelList.get(position);
showDialogBox(position, true);
}
}
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recycler_details);
populateList();
}
private void populateList() {
for (int i = 0; i < 10; i++) {
int img = R.drawable.ic_person;
String person = "Person " + i;
String name = "Person Name " + i;
String msg = "Person Last Message " + i;
detailModel model = new detailModel(person, name, msg, img);
modelList.add(model);
}
addRecycle(modelList);
}
private void addRecycle(List<detailModel> modelList) {
adapt = new detailAdapt(this, modelList, this, this);
LinearLayoutManager layout = new LinearLayoutManager(this);
layout.setSmoothScrollbarEnabled(true);
recyclerView.setAdapter(adapt);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layout);
ItemTouchHelper helper = new ItemTouchHelper(simpleCallback);
helper.attachToRecyclerView(recyclerView);
}
#Override
public void onDeleteCLick(Object obj, int position) {
showDialogBox(position, false);
}
private void showDialogBox(final int position, final boolean isSwiped) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Confirmation");
builder.setMessage("Are you sure to delete this Item");
builder.setCancelable(false);
builder.setPositiveButton("yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
deleteItem(position);
}
});
builder.setNegativeButton("no", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
if (isSwiped) {
modelList.add(position, swipeData);
adapt.notifyItemInserted(position);
}
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
private void deleteItem(final int position) {
modelData = modelList.get(position);
modelList.remove(position);
adapt.notifyItemRemoved(position);
Snackbar snackbar = Snackbar.make(recyclerView, "item removed at position " + position, Snackbar.LENGTH_LONG);
snackbar.setAction("undo", new View.OnClickListener() {
#Override
public void onClick(View v) {
modelList.add(position, modelData);
adapt.notifyItemInserted(position);
}
});
snackbar.show();
}
#Override
public void onUndoCLick(Object obj, int position) {
}
#Override
public void onSingleClick(Object obj, int position) {
detailModel model = (detailModel) obj;
Toast.makeText(this, "click at " + position, Toast.LENGTH_SHORT).show();
}
}
Please remove below
modelList.add(position, swipeData);
adapt.notifyItemInserted(position);
from the cancel button of the alert dialog, as you already didn't remove the item yet, so no need to insert it again. instead replace them with notifyItemChanged(position); like below
builder.setNegativeButton("no", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
if (isSwiped) {
adapt.notifyItemChanged(position);
}
}
});
Recntly I am working on android project with firebase, I am using recyclerview for showing data. I have added edittext and search button, when we click search button one function call and show its search relevant data. But issue is that when I click the search button it shows the data(suppose only 1 result found) when I click again search button it again append same data, and it shows again and again contineously when I click button.
I am really worried, kindly suggest me whats the issue.
My Adapter code
import android.app.LauncherActivity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
public class Find_donor_Adapter extends RecyclerView.Adapter<Find_donor_Adapter.MyViewHolder> {
Context context;
ArrayList<find_donor_helper> find_donor_helper;
public Find_donor_Adapter(Context context, ArrayList<find_donor_helper> find_donor_helper) {
this.context = context;
this.find_donor_helper = find_donor_helper;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.find_blood_layout,parent,false));
}
#Override
public void onBindViewHolder(#NonNull MyViewHolder holder, int position) {
final find_donor_helper helper = find_donor_helper.get(position);
holder.lname.setText(find_donor_helper.get(position).getFullname());
holder.bldgrp.setText(find_donor_helper.get(position).getBloodgroup());
final String n = helper.getPhonenumber();
holder.lnumber.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try
{
Intent call = new Intent(Intent.ACTION_CALL);
call.setData(Uri.parse("tel:03465987599"));
call.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(call);
}
catch (Exception e)
{
Toast.makeText(context, ""+e.getMessage(), Toast.LENGTH_LONG).show();
}
}
});
holder.ucall.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent call = new Intent(Intent.ACTION_VIEW);
call.setData(Uri.parse("sms:"+n));
call.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(call);
}
});
Picasso.get().load(helper.getUserimg()).into(holder.uimg);
}
#Override
public int getItemCount() {
return find_donor_helper.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder{
TextView lname,bldgrp;
Button lnumber,ucall;
ImageView uimg;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
lname = (TextView) itemView.findViewById(R.id.name);
bldgrp = (TextView) itemView.findViewById(R.id.bloodgroup);
lnumber = (Button) itemView.findViewById(R.id.number);
uimg = (ImageView) itemView.findViewById(R.id.userimg);
ucall = (Button) itemView.findViewById(R.id.call);
}
}
}
main code
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Toast;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
public class Find_BloodDonator extends AppCompatActivity {
RecyclerView findblood;
ArrayList<find_donor_helper> arrayList;
Find_donor_Adapter adapter;
ProgressDialog pd;
EditText searchtext;
String st;
DatabaseReference reference;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_find__blood_donator);
pd = new ProgressDialog(this);
pd.setMessage("Please wait...");
pd.setCanceledOnTouchOutside(false);
pd.setCancelable(false);
findblood = findViewById(R.id.findblood);
findblood.setLayoutManager(new LinearLayoutManager(this));
arrayList = new ArrayList<find_donor_helper>();
//alldata("blooddonor","Yes");
searchtext = findViewById(R.id.searchtext);
st = searchtext.getText().toString();
searchtext.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
alldata("bloodgroup","hello");
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
alldata("bloodgroup","hello");
}
#Override
public void afterTextChanged(Editable s) {
alldata("bloodgroup",s.toString());
}
});
}
private void alldata(String blooddonor,String bloodgroup) {
reference = FirebaseDatabase.getInstance().getReference().child("Users");
Query chk = reference.limitToLast(10).orderByChild(blooddonor).equalTo(bloodgroup);
chk.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
pd.cancel();
try {
for (DataSnapshot dataSnapshot1:dataSnapshot.getChildren())
{
find_donor_helper donor_helper = dataSnapshot1.getValue(find_donor_helper.class);
arrayList.add(donor_helper);
}
adapter = new Find_donor_Adapter(getApplicationContext(),arrayList);
findblood.setAdapter(adapter);
}
catch (Exception e)
{
pd.cancel();
Toast.makeText(Find_BloodDonator.this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
pd.cancel();
Toast.makeText(Find_BloodDonator.this, "Server error", Toast.LENGTH_SHORT).show();
}
});
}
}
When you do a new search, your onDataChange gets called with all search results. Then you currently add those search results to arrayList, which means that as you execute additional searches, the list just keeps getting longer.
To only show the results of the latest query, you need to clear arrayList before adding the new search results to it:
Query chk = reference.limitToLast(10).orderByChild(blooddonor).equalTo(bloodgroup);
chk.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
pd.cancel();
arrayList.clear()
try {
for (DataSnapshot dataSnapshot1:dataSnapshot.getChildren()) {
find_donor_helper donor_helper = dataSnapshot1.getValue(find_donor_helper.class);
arrayList.add(donor_helper);
}
adapter = new Find_donor_Adapter(getApplicationContext(),arrayList);
findblood.setAdapter(adapter);
}
catch (Exception e) {
pd.cancel();
Toast.makeText(Find_BloodDonator.this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
pd.cancel();
Toast.makeText(Find_BloodDonator.this, "Server error", Toast.LENGTH_SHORT).show();
}
});
Note that you don't need to create a new adapter every time your change arrayList. You can also modify arrayList to contain the up-to-date items (as you already do), and then simply tell the existing adapter to refresh its view(s) with the updated data.
This means you can move the creation of the adapter to your onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_find__blood_donator);
...
arrayList = new ArrayList<find_donor_helper>();
adapter = new Find_donor_Adapter(getApplicationContext(),arrayList);
findblood.setAdapter(adapter);
And then to refresh the data:
Query chk = reference.limitToLast(10).orderByChild(blooddonor).equalTo(bloodgroup);
chk.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
pd.cancel();
arrayList.clear()
try {
for (DataSnapshot dataSnapshot1:dataSnapshot.getChildren()) {
find_donor_helper donor_helper = dataSnapshot1.getValue(find_donor_helper.class);
arrayList.add(donor_helper);
}
adapter.notifyDataSetChanged();
}
catch (Exception e) {
pd.cancel();
Toast.makeText(Find_BloodDonator.this, ""+e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
pd.cancel();
Toast.makeText(Find_BloodDonator.this, "Server error", Toast.LENGTH_SHORT).show();
}
});
I have a RecyclerView class (QuestionCardAdapter) that presents all the items of a SpanishQuestionSet as CardViews.
Everything had been working fine (for instance i could make it so when a card was clicked, 'tick' and 'cross' buttons would come up and would remove the card when clicked)
However recently I wanted the clicking of the buttons (vCross or VTick) to modify an array which is a part of the SpanishQuestionSet (i.e. the item in the array would be +1 for wrong and -1 for right so that the descending quicksort i use will cause questions answered incorrectly to be at the top).
However, whenever I say click 4 consecutive cards as wrong, instead of each card's score being increased by 1, the first card of the 4's score is increased by 4. It seems like getAdapterPosition() is delayed. Could it be affected by a time limit variable I added so that the app wouldnt crash if someone double clicked a button before the card remove animation had completed?
Any help would be appreciated and I will present below the adapter and SpanishQuestionSet classes.
The adapter class is most likely the focus.
package com.alexgower.odin_spanishpack;
import android.content.Context;
import android.graphics.Color;
import android.os.SystemClock;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.FileNotFoundException;
import java.util.List;
public class QuestionCardAdapter extends RecyclerView.Adapter<QuestionCardAdapter.QuestionCardViewHolder> {
private final Context context;
protected List<QuestionCardInfo> questionCardList;
private long mLastClickTime = 0;
private SpanishQuestionSet questionSet;
private int positionClicked;
private void setPositionClicked(int i){
this.positionClicked =i;
}
private int getPositionClicked(){
return this.positionClicked;
}
public QuestionCardAdapter(Context contextIn, List<QuestionCardInfo> questionCardList, SpanishQuestionSet questionSetIn) {
this.questionCardList = questionCardList;
this.context = contextIn;
this.questionSet = questionSetIn;
}
#Override
public int getItemCount() {
return questionCardList.size();
}
#Override
public void onBindViewHolder(QuestionCardViewHolder questionCardViewHolder, int i) {
QuestionCardInfo ci = questionCardList.get(i);
questionCardViewHolder.vQuestionAnswer.setText(String.valueOf(ci.score) + ci.question);
questionCardViewHolder.answer = ci.answer;
questionCardViewHolder.vTick.setVisibility(View.INVISIBLE);
questionCardViewHolder.vCross.setVisibility(View.INVISIBLE);
questionCardViewHolder.vColorTV.setBackgroundColor(questionSet.getColourForScore(context,ci.score));
}
#Override
public QuestionCardViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.question_card_layout, viewGroup, false);
return new QuestionCardViewHolder(itemView);
}
public class QuestionCardViewHolder extends RecyclerView.ViewHolder {
public View view;
protected TextView vQuestionAnswer;
protected TextView vColorTV;
protected ImageView vTick;
protected ImageView vCross;
protected String answer = "Error";
public QuestionCardViewHolder(View v) {
super(v);
vColorTV = (TextView) v.findViewById(R.id.forNowColourTextView);
vQuestionAnswer = (TextView) v.findViewById(R.id.questionAnswerTextView);
vTick = (ImageView) v.findViewById(R.id.tickImage);
vCross = (ImageView) v.findViewById(R.id.crossImage);
view = v;
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
vQuestionAnswer.setText(answer);
vTick.setVisibility(View.VISIBLE);
vCross.setVisibility(View.VISIBLE);
setPositionClicked(getAdapterPosition());
}
});
view = vTick;
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (SystemClock.elapsedRealtime() - mLastClickTime > 1000) {
questionSet.questionRight(getPositionClicked(),context);
//questionSet.saveScores(context);
Toast.makeText(context, String.valueOf(questionSet.getScore(getPositionClicked())), Toast.LENGTH_LONG).show();
removeAt(getPositionClicked());
mLastClickTime = SystemClock.elapsedRealtime();
}
}
});
view = vCross;
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (SystemClock.elapsedRealtime() - mLastClickTime > 1000) {
questionSet.questionWrong(getPositionClicked(),context);
Toast.makeText(context, String.valueOf(questionSet.getScore(getPositionClicked())), Toast.LENGTH_LONG).show();
removeAt(getPositionClicked());
mLastClickTime = SystemClock.elapsedRealtime();
}
}
});
}
}
public void testContext(int position) {
questionSet.testFile(position, context);
//String name = questionSet.getQuestion(position);
//try {
// context.openFileOutput("a.txt", Context.MODE_PRIVATE);
// Toast.makeText(context, name, Toast.LENGTH_SHORT).show();
//}catch(FileNotFoundException e){
// Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
//}
}
public void removeAt(int position) {
questionCardList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, questionCardList.size());
}
SpanishQuestionSet class
package com.alexgower.odin_spanishpack;
import android.content.Context;
import android.graphics.Color;
import android.os.SystemClock;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.FileNotFoundException;
import java.util.List;
public class QuestionCardAdapter extends RecyclerView.Adapter<QuestionCardAdapter.QuestionCardViewHolder> {
private final Context context;
protected List<QuestionCardInfo> questionCardList;
private long mLastClickTime = 0;
private SpanishQuestionSet questionSet;
private int positionClicked;
private void setPositionClicked(int i){
this.positionClicked =i;
}
private int getPositionClicked(){
return this.positionClicked;
}
public QuestionCardAdapter(Context contextIn, List<QuestionCardInfo> questionCardList, SpanishQuestionSet questionSetIn) {
this.questionCardList = questionCardList;
this.context = contextIn;
this.questionSet = questionSetIn;
}
#Override
public int getItemCount() {
return questionCardList.size();
}
#Override
public void onBindViewHolder(QuestionCardViewHolder questionCardViewHolder, int i) {
QuestionCardInfo ci = questionCardList.get(i);
questionCardViewHolder.vQuestionAnswer.setText(String.valueOf(ci.score) + ci.question);
questionCardViewHolder.answer = ci.answer;
questionCardViewHolder.vTick.setVisibility(View.INVISIBLE);
questionCardViewHolder.vCross.setVisibility(View.INVISIBLE);
questionCardViewHolder.vColorTV.setBackgroundColor(questionSet.getColourForScore(context,ci.score));
}
#Override
public QuestionCardViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.question_card_layout, viewGroup, false);
return new QuestionCardViewHolder(itemView);
}
public class QuestionCardViewHolder extends RecyclerView.ViewHolder {
public View view;
protected TextView vQuestionAnswer;
protected TextView vColorTV;
protected ImageView vTick;
protected ImageView vCross;
protected String answer = "Error";
public QuestionCardViewHolder(View v) {
super(v);
vColorTV = (TextView) v.findViewById(R.id.forNowColourTextView);
vQuestionAnswer = (TextView) v.findViewById(R.id.questionAnswerTextView);
vTick = (ImageView) v.findViewById(R.id.tickImage);
vCross = (ImageView) v.findViewById(R.id.crossImage);
view = v;
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
vQuestionAnswer.setText(answer);
vTick.setVisibility(View.VISIBLE);
vCross.setVisibility(View.VISIBLE);
setPositionClicked(getAdapterPosition());
}
});
view = vTick;
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (SystemClock.elapsedRealtime() - mLastClickTime > 1000) {
questionSet.questionRight(getPositionClicked(),context);
//questionSet.saveScores(context);
Toast.makeText(context, String.valueOf(questionSet.getScore(getPositionClicked())), Toast.LENGTH_LONG).show();
removeAt(getPositionClicked());
mLastClickTime = SystemClock.elapsedRealtime();
}
}
});
view = vCross;
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (SystemClock.elapsedRealtime() - mLastClickTime > 1000) {
questionSet.questionWrong(getPositionClicked(),context);
Toast.makeText(context, String.valueOf(questionSet.getScore(getPositionClicked())), Toast.LENGTH_LONG).show();
removeAt(getPositionClicked());
mLastClickTime = SystemClock.elapsedRealtime();
}
}
});
}
}
public void testContext(int position) {
questionSet.testFile(position, context);
//String name = questionSet.getQuestion(position);
//try {
// context.openFileOutput("a.txt", Context.MODE_PRIVATE);
// Toast.makeText(context, name, Toast.LENGTH_SHORT).show();
//}catch(FileNotFoundException e){
// Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
//}
}
public void removeAt(int position) {
questionCardList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, questionCardList.size());
}
}
Turns out it is quite easy. For anyone in the future with a similar problem, note that getAdapterView() simply returns the integer of a views position in the viewholder so when a view is removed, the next view takes its position.
i.e. if you have views 1,2,3,4,5. When you remove 2, 3 becomes 2 and 4 becomes 3 etc. Alternative explanation: whichever is the 5th view on the screen will have position 5, even if 10000 other items before it have been removed (it will not be position 10005).
So it was not a problem with getAdapterPostion(). To fix the problem I used a variable for an itemID for each view in the recyclerview and did not use getAdapterPosition() except for in the removeAt() method.