На основе вашего кода ниже отображается список пользователей в RecyclerView. Нажатие на элемент приведет к тому, что электронная почта этого пользователя будет отображаться в textViewName TextView.
Кроме того, если долго щелкнуть элемент в отображаемом списке, он удалит соответствующего пользователя из базы данных и обновит RecyclerView в соответствии с измененной базой данных.
Используется только одно действие MainActivity (поэтому исходное письмо жестко запрограммировано).
код
User.java (КОД ДОБАВЛЕНО)
Чтобы упростить добавление некоторых тестовых пользователей, следующий код, конструктор, позволяющий создавать пользователя с параметрами и конструктором по умолчанию, может не существовать: -
public User() {}
public User(String name, String email, String password, String phonenumber, String productcode) {
this.id = -1;
this.name = name;
this.email = email;
this.password = password;
this.phonenumber = phonenumber;
this.productcode = productcode;
}
UserListRefreshed.java (NEW)
Это интерфейс, который реализуется MainActivity и вызывается адаптером RecyclerView при нажатии элемента (для обновления TextView), а также при длительном нажатии элемента для обновления списка.
public interface UserListRefreshed {
void userListRefreshed();
void userRetrieved(User user);
}
DatabaseHelper.java
Все db.close () удалены, неэффективно продолжать закрывать базу данных, и возникли проблемы с исходным кодом при закрытом db.
Был добавлен новый метод для удаления строки пользователя путем передачи идентификатора, а не пользователя согласно (это также возвращает количество удаленных строк, так что это можно проверить на 0, в этом случае не было бы необходимости обновить список (эта проверка не была включена): -
//<<<<<<<<<< ADDED >>>>>>>>>>
public int deleteUserById(int id) {
SQLiteDatabase db = this.getWritableDatabase();
return db.delete(TABLE_USER,COLUMN_USER_ID+"=?",new String[]{String.valueOf(id)});
}
UserRecyclerAdapter.java
Большая часть изменений относится к onBindViewHolder и является добавлением прослушивателей click / long-click.
public class UsersRecyclerAdapter extends RecyclerView.Adapter<UsersRecyclerAdapter.UserViewHolder> {
private List<User> listUsers;
public UsersRecyclerAdapter(List<User> listUsers) {
this.listUsers = listUsers;
}
@Override
public UserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// inflating recycler item view
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.user_recycler, parent, false);
return new UserViewHolder(itemView);
}
@Override
public void onBindViewHolder(UserViewHolder holder, final int position) {
holder.textViewName.setText(listUsers.get(position).getName());
holder.textViewEmail.setText(listUsers.get(position).getEmail());
holder.textViewPassword.setText(listUsers.get(position).getPassword());
holder.textPhoneNumber.setText( listUsers.get( position ).getPhonenumber() );
holder.textProductCode.setText( listUsers.get( position ).getProductcode() );
/**
* IS this what is wanted?? i.e. get the user that has been clicked?
*/
((View)holder.textViewName.getParent()).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
((MainActivity)v.getContext()).userRetrieved(listUsers.get(position));
}
});
//<<<<<<<<<< ADDITIONAL
((View)holder.textViewName.getParent()).setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(final View v) {
final int idToDelete = listUsers.get(position).getId(); //<<<<<<<<<< get the id of the user that was long-clicked
new Thread(new Runnable() {
@Override
public void run() {
DatabaseHelper dbhlpr = new DatabaseHelper(v.getContext());
dbhlpr.deleteUserById(idToDelete);
((MainActivity)v.getContext()).userListRefreshed();
}
}).start();
return true;
}
});
}
@Override
public int getItemCount() {
Log.v(UsersRecyclerAdapter.class.getSimpleName(),""+listUsers.size());
return listUsers.size();
}
/**
* ViewHolder class
*/
public class UserViewHolder extends RecyclerView.ViewHolder {
public AppCompatTextView textViewName;
public AppCompatTextView textViewEmail;
public AppCompatTextView textViewPassword;
public AppCompatTextView textPhoneNumber;
public AppCompatTextView textProductCode;
public UserViewHolder(View view) {
super(view);
textViewName = view.findViewById( R.id.textViewName);
textViewEmail = view.findViewById(R.id.textViewEmail);
textViewPassword = view.findViewById(R.id.textViewPassword);
textPhoneNumber = view.findViewById(R.id.textViewPhone_number);
textProductCode = view.findViewById(R.id.textViewProduct_Code);
}
}
}
MainActivity.java
Это эквивалент вашей пользовательской активности
Вместо того, чтобы подавлять предупреждение об утечке памяти, был добавлен альтернативный безопасный метод с именем getUserList () .
Обратите внимание, что теперь RecyclerView управляется методом manageRecyclerView , который принимает List. Если адаптер имеет значение null, тогда он и RecyclerView настроены, в противном случае список обновляется новым списком, переданным методу.
Activity реализует интерфейс UserListRefreshed и поэтому требует, чтобы использовались методы шаблона, чтобы были добавлены методы userListRefreshed и userRetrieved .
Для предоставления данных тестирования был добавлен метод addSomeDataIfNone . Это добавляет двух пользователей, если не существует ни одного пользователя.
public class MainActivity extends AppCompatActivity implements UserListRefreshed {
//private AppCompatActivity activity = MainActivity.this;
private AppCompatTextView textViewName;
private RecyclerView recyclerViewUsers;
private List<User> listUsers = new ArrayList<>(); // Always initially going to be empty so define it here
private UsersRecyclerAdapter usersRecyclerAdapter;
private DatabaseHelper databaseHelper;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView( R.layout.userlistactivity);
// getSupportActionBar().setTitle("");
//Toast.makeText(getApplicationContext(),"inside user Activity",Toast.LENGTH_SHORT).show();
databaseHelper = new DatabaseHelper(this); //<<<<<<<<<< Instiate the Database helper
initViews();
initObjects();
addSomeDataIfNone(); // Add some testing data FOR TESTING/DEMONSTRATION
getUserList(); //<<<<<<<<<< get the data
}
/**
* This method is to initialize views
*/
private void initViews() {
textViewName = (AppCompatTextView) findViewById(R.id.textViewName);
recyclerViewUsers = (RecyclerView) findViewById(R.id.recyclerViewUsers);
}
/**
* This method is to initialize objects to be used
*/
private void initObjects() {
/*
<<<<<<<<<< SEE manageRecyclerView >>>>>>>>>>
listUsers = new ArrayList<>();
usersRecyclerAdapter = new UsersRecyclerAdapter(listUsers);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerViewUsers.setLayoutManager(mLayoutManager);
recyclerViewUsers.setItemAnimator(new DefaultItemAnimator());
recyclerViewUsers.setHasFixedSize(true);
recyclerViewUsers.setAdapter(usersRecyclerAdapter);
databaseHelper = new DatabaseHelper(activity);
*/
manageRecyclerView(new ArrayList<User>()); //<<<<<<<<<<
String emailFromIntent = getIntent().getStringExtra("EMAIL");
emailFromIntent = "mtnobody@nobodymail.com"; //<<<<<<<<<< as only the one activity email initially hardcoded
textViewName.setText(emailFromIntent);
//getDataFromSQLite(); see OUCH
//getUserList(); //<<<<<<<<< alternative with no OUCH
}
//<<<<<<<<<< REDUNDANT Replaced by getUserList >>>>>>>>>>
// No potential memory leak with getUserList
/**
* This method is to fetch all user records from SQLite
*/
@SuppressLint("StaticFieldLeak") //!!!!!!!!!! OUCH
private void getDataFromSQLite() {
final List<User> newUserList = new ArrayList<>();
// AsyncTask is used that SQLite operation not blocks the UI Thread.
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
newUserList.addAll(databaseHelper.getAllUser());
listUsers.addAll(databaseHelper.getAllUser());
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
usersRecyclerAdapter.notifyDataSetChanged();
}
}.execute();
}
/**
* Manage the RecyclerView
* i.e. either set it up or refresh the list
*/
private void manageRecyclerView(List<User> thelist) {
if (usersRecyclerAdapter == null) {
usersRecyclerAdapter = new UsersRecyclerAdapter(listUsers);
RecyclerView.LayoutManager lom = new LinearLayoutManager(this);
recyclerViewUsers.setLayoutManager(lom);
recyclerViewUsers.setItemAnimator(new DefaultItemAnimator());
recyclerViewUsers.setHasFixedSize(true);
recyclerViewUsers.setAdapter(usersRecyclerAdapter);
} else {
listUsers.clear();
listUsers.addAll(thelist);
}
usersRecyclerAdapter.notifyDataSetChanged();
}
/**
* Get the UserList off the UI thread and then refresh the RecyclerView on the UI thread
*/
private void getUserList() {
new Thread(new Runnable() {
@Override
public void run() {
final List<User> ul = databaseHelper.getAllUser();
runOnUiThread(new Runnable() {
@Override
public void run() {
manageRecyclerView(ul);
}
});
}
}).start();
}
@Override
public void userListRefreshed() {
getUserList();
}
/**
* The Interface method called from within the
* @param user
*/
@Override
public void userRetrieved(User user) {
textViewName.setText(user.getEmail());
}
private void addSomeDataIfNone() {
if (databaseHelper.getAllUser().size() > 0 ) return;
databaseHelper.addUser(new User("Fred","fred@fredmail.com","password","1234567890","00000000001"));
databaseHelper.addUser(new User("Bbert","bert@bertmail.com","password","1234567890","00000000001"));
}
}
Тестирование / Результаты
Первый запуск: -
- Обратите внимание на электронную почту по умолчанию.
Нажав на Фреда, электронная почта изменится
- щелчок в любом месте строки работает (слушатели используют
view.getParent()
)
- Точно так же, нажав на Берта, отобразится электронная почта Берта.
Длинный щелчок Берт: -
- Берт был удален и дисплей обновился
Приложение Rerun: -
- Берт все еще удален
- Если Fred и Bert были удалены, то из-за проверки, выполненной методом addSomeDataIfNone, они будут добавлены снова (но поскольку у вас закодировано AUTOINCREMENT, у них будут более высокие идентификаторы).
P.S. неэффективно использовать AUTOINCREMENT
, INTEGER PRIMARY KEY
само по себе, это будет работать и без накладных расходов Автоинкремент SQLite , в первой строке которого указано: -
Ключевое слово AUTOINCREMENT накладывает дополнительные затраты ресурсов процессора, памяти, дискового пространства и дискового ввода-вывода, и их следует избегать, если в этом нет особой необходимости. Обычно не требуется. (выделение добавлено)