Actualiser RecyclerView avec les dernières données de façon dynamique
J'ai une base de données SQLite dans mon application pour laquelle j'ai fait un ContentProvider
classe.
J'ai aussi un RecyclerView dans lequel je charge un ArrayList
d'objets dans son adaptateur pour remplir la RecyclerView.
Actuellement, lorsque l'activité commence, je reçois un Cursor
via mon ContentProvider
, en boucle par le biais de la Cursor
pour créer un ArrayList
des objets que j'ai ensuite défini dans le cadre de mon RecyclerView.Adapter
.
Tout ce qui fonctionne, mais ce que je veux vraiment, c'est pour mon RecyclerView de mettre à jour dynamiquement lorsque de nouvelles données sont chargées dans la base de données SQLite via le fournisseur de contenu.
J'ai vu des postes de l'inscription de cette bibliothèque CursorRecyclerAdapter mais je ne veux pas l'utiliser parce que vous n'obtenez pas la belle RecyclerView animations sur insérer/supprimer.
J'essayais d'une certaine façon utiliser le LoaderManager.LoaderCallbacks<Cursor>
de retour d'appel des méthodes pour obtenir un curseur, convertir arraylist, le swap que dans mon RecyclerView adaptateur, mais ne pouvait pas le comprendre.
Quelqu'un pourrait-il svp me montrer un exemple de code sur la façon de les mettre en place dans mon Activité, de sorte que le RecyclerView
s'actualise lorsque de nouvelles données sont écrites dans la base de données locale via un fournisseur de contenu?
Voici ce que ma RecyclerView.Adaptateur ressemble:
public class MyAdapter extends RecyclerView.Adapter<AdapterTodoList.Holder> {
private List<TodoItem> itemList;
private Context mContext;
//data
String message;
Long datetime;
//this class takes a context and a list of the items you want to populate into the recycler view
public AdapterTodoList(Context context, List<TodoItem> itemList) {
this.itemList = itemList;
this.mContext = context;
}
@Override
public Holder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
//our xml showing how one row looks
View row = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recycler_view_todo_item, viewGroup, false);
Holder holder = new Holder(row);
return holder;
}
@Override
public void onBindViewHolder(Holder holder, final int position) {
holder.recyclerLinearLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(mContext, "Recycle Click" + position, Toast.LENGTH_SHORT).show();
}
});
//get one item
TodoItem data = itemList.get(position);
Log.d("Test", "onBindViewHolder position " + position);
message = data.getMessage();
datetime = data.getDatetime();
//convert long to date
String dateString = new SimpleDateFormat("MM/dd/yyyy").format(new Date(datetime));
//set the holder
holder.messageTextView.setText(message);
}
@Override
public int getItemCount() {
return itemList.size();
}
public class Holder extends RecyclerView.ViewHolder {
protected ImageView checkBoxImageView;
protected TextView messageTextView;
protected LinearLayout recyclerLinearLayout;
public Holder(View view) {
super(view);
//checkBoxImageView = (ImageView) view.findViewById(R.id.checkBoxImageView);
messageTextView = (TextView) view.findViewById(R.id.messageTextView);
//the whole view
recyclerLinearLayout = (LinearLayout) view.findViewById(R.id.recyclerItemLinearLayout);
}
}
}
Voici ce que mon Activité ressemble comme jusqu'à présent:
public class HomeRec extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor>{
private Toolbar mToolbar;
//recyclerview and adapter
private RecyclerView mRecyclerView;
private MyAdapter adapter;
//the swipe refresh layout that wraps the recyclerview
private SwipeRefreshLayout mSwipeRefreshLayout;
//this will hold all of our results from our query.
List<TodoItem> itemList = new ArrayList<TodoItem>();
private Cursor mCursor;
//resources from layout
EditText toDoEditText;
Button cancelButton;
Button addButton;
//variables
private String message;
private long datetime;
//loader
private SimpleCursorAdapter mTodoAdapter;
private static final int TODO_LOADER = 0;
//These indices are tied to Projection. If Projection changes, these
//must change.
public static final int COL_ID = 0;
public static final int COL_MESSAGE = 1;
public static final int COL_DATETIME = 2;
public static final int COL_CHECKED = 3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_rec);
mToolbar = (Toolbar) findViewById(R.id.app_bar);
//set the Toolbar as ActionBar
setSupportActionBar(mToolbar);
//Initialize recycler view //
mRecyclerView = (RecyclerView) findViewById(R.id.todoRecyclerView);
mRecyclerView.hasFixedSize();
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
//set a grey line divider for each item in recycler view
mRecyclerView.addItemDecoration(
new DividerItemDecoration(this, null, false, true));
//END Initialize recycler view //
//initiate the swipe to refresh layout
mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
//Refresh items
refreshItems();
}
void refreshItems() {
//Load items
//...
//Load complete
onItemsLoadComplete();
}
void onItemsLoadComplete() {
//Update the adapter and notify data set changed
//...
//Stop refresh animation
mSwipeRefreshLayout.setRefreshing(false);
}
});
//set colors for swipe to refresh
mSwipeRefreshLayout.setColorSchemeResources(
R.color.refresh_progress_2,
R.color.refresh_progress_3);
//fire my asynctask to get data for the first time
new MessagesAsyncTask().execute();
}
@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_home_rec, menu);
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();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
//Not sure what to do here or how to make this work.
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
//Not sure what to do here or how to make this work.
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
//Not sure what to do here or how to make this work.
}
public class MessagesAsyncTask extends AsyncTask<Void, Void, List<TodoItem>> {
//the cursor for the query to content provider
private Cursor mCursor;
@Override
protected void onPreExecute() {
}
@Override
protected List<TodoItem> doInBackground(Void... params) {
//A "projection" defines the columns that will be returned for each row
String[] projection =
{
DataProvider.COL_ID, //Contract class constant for the COL_ID column name
DataProvider.COL_MESSAGE, //Contract class constant for the COL_MESSAGE column name
DataProvider.COL_DATETIME, //Contract class constant for the COL_DATETIME column name
DataProvider.COL_CHECKED //Contract class constant for the COL_CHECKED column name
};
//Defines a string to contain the selection clause
String selectionClause = null;
//An array to contain selection arguments
String[] selectionArgs = null;
//An ORDER BY clause, or null to get results in the default sort order
String sortOrder = DataProvider.COL_DATETIME + " DESC";
//Does a query against the table and returns a Cursor object
mCursor = getContentResolver().query(
DataProvider.CONTENT_URI_TODO, //The content URI of the Todo table
projection, //The columns to return for each row
selectionClause, //Either null, or the word the user entered
selectionArgs, //Either empty, or the string the user entered
sortOrder); //The sort order for the returned rows
//Some providers return null if an error occurs, others throw an exception
if (null == mCursor) {
//Insert code here to handle the error.
} else if (mCursor.getCount() < 1) {
//If the Cursor is empty, the provider found no matches
} else {
//Insert code here to do something with the results
}
//convert cursor to arraylist of objects
while (mCursor.moveToNext()) {
itemList.add(new TodoItem(mCursor.getInt(mCursor.getColumnIndex(DataProvider.COL_ID)),
mCursor.getString(mCursor.getColumnIndex(DataProvider.COL_MESSAGE)),
mCursor.getLong(mCursor.getColumnIndex(DataProvider.COL_DATETIME)),
mCursor.getInt(mCursor.getColumnIndex(DataProvider.COL_CHECKED))
));
}
mCursor.close();
return itemList;
}
@Override
protected void onPostExecute(List<TodoItem> itemList) {
if (!itemList.isEmpty()) {
adapter = new MyAdapter(HomeRec.this, itemList);
mRecyclerView.setAdapter(adapter);
} else {
Toast.makeText(getApplicationContext(), "No data to display", Toast.LENGTH_LONG).show();
}
}
}
}
onBindViewHolderCursor
méthode, si vous n'êtes pas sûr de ce que Cursor
paramètre est à onBindViewHolderCursor
essayer d'appeler DatabaseUtils#dumpCurrentRow()
Je suis désolé. Je ne comprends toujours pas. J'ai besoin d'une réponse plus complète avec des exemples de code pour expliquer ce qui est pourquoi j'ai fait une nouvelle question. Je vous remercie bien.
comme je l'ai dit étendre:
class MyAdapter extends CursorRecyclerAdapter { ....
Mais alors quoi? Où dois-je interroger ma base de données SQLite avec mon ContentProvider? Comment mon Activité ressemble et où aurais-je définir ce que l'Adaptateur pour mon RecyclerView? Dois-je besoin de rien de spécial dans ma ContentProvider? J'ai l'impression d'être aveugle, sans aucun exemple de code =(
avez-vous vu un exemple de code avec CursorLoader? il est 100% la même chose... voir: developer.android.com/intl/ru/guide/components/loaders.html par exemple
OriginalL'auteur Micro | 2015-09-11
Vous devez vous connecter pour publier un commentaire.
Je ne suis pas sûr de ce que vous avez besoin, mais je pense que vous devriez ajouter cette méthode À la carte et de l'appeler une fois que vos données ont été extraites
Espère que cela aidera 😀
Nice. Il a résolu mon problème.
OriginalL'auteur WinHtaikAung
de votre question, je suppose que vous chargez les données de la base de données et quelque part, il est un code qui est la mise à jour de la base de données. Et à chaque mise à jour que vous souhaitez mettre à jour votre RecyclerView, Si c'est le cas, poursuivez votre lecture. Je ne vais pas expliquer ce complètement, mais il y a beaucoup de source qui va vous l'expliquer.
Utilisation BroadcastReciever : À l'endroit où vous êtes à la mise à jour de votre base de données
sendBroadcast()
. Et dans l'activité utiliser le BroadcastReceiverexemple et dans le
onReceive()
appel de fonction charger les données dans votre liste de tableaux et d'appeler laadapter.notifyDataSetChanged()
OriginalL'auteur Deepak Baliga
Au lieu de faire la nouvelle carte à chaque fois dans onPostExecute et mis à recyclerview de nouveau, vous pouvez en informer l'adaptateur après la modification de la liste des éléments.
OU
Si vous voulez faire de l'adaptateur à l'aide de liste de tableaux au lieu de cursoradapter à l'aide du chargeur, j'ai fait l'échantillon pour vous avec les données fournies par vous. Vous pouvez l'utiliser comme une référence:
OriginalL'auteur Akash Jain
De "l'écoute" de votre
ContentProvider
changements, vous aurez peut essayer d'intégrerContentObserver
dans votreContentProvider
, de sorte qu'il peut déclencher les événements requis lorsqu'une transaction est effectuée sur votreContentProvider
. Après quoi, vous allez déclarer unContentObserver
à votreCONTENT_URI
, alors vous pouvez déclencher une mise à jour de votreRecyclerView
.Plus d'informations sur la mise en œuvre de
ContentObserver
ici.Un exemple de code pour la mise à jour d'un élément dans votre
RecyclerView
serait,Où
T
est le type d'objet si votre ligne renvoie,mLock
est juste une instance de l'objet à acquérir un verrou,mData
la liste des éléments que vous avez fournis pour votreRecyclerView
. Vous obtenez l'essentiel. 😀Espère que cela aide.
OriginalL'auteur deubaka
Actualiser curseur à chaque seconde
cochez cette méthode ont des problèmes de performances ou de meilleure méthode que ce
si vous avez s'il vous plaît noter ici
OriginalL'auteur Rangana Fernando