RecyclerView не отображает вставленные данные SQLite мгновенно
Когда пользователь из FragmentDialog
введите свои данные в edittexts и нажмите кнопку сохранения, данные должны немедленно отображаться в recyclerView
, но это не произойдет. Чтобы получить/показать последние данные, необходимо перезапустить приложение
Я использовал временное решение, где передаю данные из FragmentDialog
в mainActivity
через интерфейс, а затем я передаю эти данные в arraylist для recyclerView. Эта работа, но dosn't выглядят как пропортивное решение. Я желаю "правильного" способа сделать это
Я также попытался установить adapter.notifyDataSetChanged(); в разных местах без каких-либо ограничений
Класс DialogFragment, в котором пользователь вводит свои данные и затем вставляется в базу данных SQLite
public class DialogAdd extends DialogFragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.add_productdialog,container, false);
name = (EditText) rootView.findViewById(R.id.dialog_productname);
quantity = (EditText) rootView.findViewById(R.id.dialog_qantity);
location = (EditText) rootView.findViewById(R.id.dialog_location);
normalPrice = (EditText) rootView.findViewById(R.id.dialog_normalPrice);
offerPrice = (EditText) rootView.findViewById(R.id.dialog_offerPrice);
okButton = (Button) rootView.findViewById(R.id.dialog_okButton);
okButton.getBackground().setColorFilter(Color.parseColor("#2fbd4b"), PorterDuff.Mode.MULTIPLY);
okButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (name.getText().toString().isEmpty()) {
Toast.makeText(context, "You must add a name", Toast.LENGTH_LONG).show();
} else {
DialogAddListener addListener = (DialogAddListener) getActivity();
dbHelper.insertData(name.getText().toString(), quantity.getText().toString(), location.getText().toString(), normalPrice.getText().toString(), offerPrice.getText().toString());
addListener.getDialogData(name.getText().toString(), quantity.getText().toString(), location.getText().toString(), normalPrice.getText().toString(), offerPrice.getText().toString());
getDialog().dismiss();
}
}
});
return rootView;
}
Класс mainActivity, который создает экземпляр recyclerview, sqlite и адаптеров.
public class MainActivity extends AppCompatActivity implements DialogAdd.DialogAddListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.shoppinglist_mainactivity);
databaseHelper = new DatabaseHelper(this);
addbutton = (ImageButton) findViewById(R.id.addbtn);
addbutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dialogAdd = new DialogAdd();
dialogAdd.show(getSupportFragmentManager(), "addDialog");
}
});
//RecyclerView
recyclerView = (RecyclerView)findViewById(R.id.rv_shoppinglist);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(App.getAppContex());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(linearLayoutManager);
initializeData();
adapter = new ShoplistAdapter(shopListItems);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
private void initializeData(){
shopListItems = new ArrayList<>();
resultset = databaseHelper.getAllData();
if (resultset.moveToFirst()){
while(!resultset.isAfterLast()){
shopListItems.add(new ShopListItem(resultset.getString(1), resultset.getString(2), resultset.getString(3), resultset.getString(4), resultset.getString(5)));
resultset.moveToNext();
totalPrice.setText("Total cost: $" + "26");
totalItems.setText("Total items: " + resultset.getCount());
}
}
resultset.close();
}
//This is only used to show the data instantly
@Override
public void getDialogData(String name, String qty, String location, String price1, String price2) {
shopListItems.add(new ShopListItem(name, qty, location, price1, price2));
}
}
Ответы
Ответ 1
Вы должны использовать CursorLoader, который автоматически прослушивает изменения в Uri
. И уведомите изменения через contentResolver.notifyChanged(uriOfInsertedData)
. Путь зверя состоит в использовании ContentProvider
, чтобы сделать все вещи тонкой работы соответствующим образом.
Или проще, зарегистрируйте Observer в singleton для вашей базы данных и сообщите об этом при изменении. В общем, это будет делать то же самое, и у вас не будет никаких отношений между компонентами. Это займет некоторый код для публикации, поэтому я надеюсь, что вы это выясните.
Обновление 2016-03-09, на основе вашего комментария
Если вы выполнили пример 1, он не сообщил вам, как отслеживать изменения. Для этого случая не существует существующего механизма.
Наилучшим подходом к реализации этого механизма является использование шаблона Observer.
Я бы пошел с синглом, в котором размещаются наблюдатели.
Вы можете расширить Observable (у которого уже есть логика для хранения списка наблюдателей, уведомление и удаление) и сделать одноэлемент он.
Зарегистрировать наблюдателя, вызвав addObserver()
везде, где вам нужно прослушать (не забудьте вызвать deleteObserver()
, чтобы избежать утечек активности).
Теперь, когда вы вызываете insert
или каким-либо образом изменяете базу данных, обязательно вызывайте notifyObservers("tablename")
из Observable
singleton.
Таким образом, все наблюдатели получат уведомление о том, что таблица была изменена (передача имени таблицы является примером, вы можете использовать любой объект там, чтобы сообщить вашим компонентам об изменении)
Затем в update()
вашего Observer
проверьте, обновляется ли таблица, которую вы хотите контролировать, если это так, перезагрузите данные, как обычно.