J'ai une liste de recyclerview d'éléments de carte de carte qui fonctionne correctement. Lors de la création d'une nouvelle carte qui est insérée dans la base de données, je voudrais déclencher un toast qui informe l'utilisateur que la View a été ajoutée avec succès et afficher le numéro de CardView. Le numéro de CardView est l'ID de l'élément CardView inséré dans la base de données. Les données sont enregistrées dans la base de données lorsque l'utilisateur clique sur un bouton d'enregistrement qui déclenche OnClickSave ().
I Configurez une @query dans le DAO pour obtenir le max (cardid): P>
public class SQLiteDB extends SQLiteOpenHelper { ... public int getLastInsertId() { int index = 0; SQLiteDatabase sdb = getReadableDatabase(); Cursor cursor = sdb.query( "sqlite_sequence", new String[]{"seq"}, "name = ?", new String[]{TABLE_NAME}, null, null, null, null ); sdb.beginTransaction(); try { if (cursor !=null) { if (cursor.moveToLast()) { index = cursor.getInt(cursor.getColumnIndex("seq")); } } ... } return index; }
3 Réponses :
En raison de l'utilisation de l'asyncaptage pour insérer une carte à la base de données, cette fonction prend un certain temps pour terminer et vous montrer votre toast, instantanément! Changez votre activité à ceci:
AddorUpdateCardActivity ... private int newMax = -1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mViewModel = new ViewModelProvider(this).get(cardViewModel.class); mViewModel.getMax().observe(this, integer2 -> { newMax = integer2; Toast.makeText(AddorUpdateCardActivity.this, "card #" + newMax + " was saved to the list", Toast.LENGTH_LONG).show(); hideProgressBar(); }); } public void onClickSave(View v) { //set card data // then insert data in database mViewModel.insertCard(card1); showProgressBar(); }
Je voudrais que le toast soit tiré après que l'utilisateur clique sur Insère les nouvelles données de View dans la base de données. Donc, je ne devrais pas devoir déplacer le code d'observateur de mviewmodel.getmax () ... sur Oncreate () et le mettre juste après Mviewmodel.insercard () dans l'Onclicksave ()? Sinon, comment le toast est-il déclenché s'il est assis sur Oncreate ()?
De plus, l'application se bloque lorsque la liste est vide et que j'essaie d'ajouter la première carte à l'aide de AddorupDatCardActivity. Le logcat dit que l'entier est Null Object Référence.
La salle Déplacez le message code> Toast code> à l'intérieur de la méthode À ce stade, le code doit fonctionner, mais vous obtiendrez plusieurs événements Insérer code> Fonctionnement à l'intérieur
AsynccTask code> prend un certain temps avant que la variable
maxcount code> est mise à jour. Puisque vous montrez le
toast code> à l'intérieur d'un bouton Cliquez, le message est affiché immédiatement sans recevoir la valeur mise à jour de
LivetaA code>.
Obverve () CODE> de sorte qu'il ne soit déclenché qu'après un
LivetaA code> Changement. P> XXX PRE>
LiveTata code> pour un seul
Insérer code>. Cela se passe parce que vous avez utilisé 2 instances distinctes de dao fort> pour
insert code> et
requête code> opération. P>
public cardRepository(Application application) {
RoomDatabase db = RoomDatabase.getDatabase(application);
cardDao = db.cardDao();
}
public LiveData<Integer> getMax() {
return cardDao.getMax();
}
public void insertCard(Card newcard) {
AsyncTask.execute(() -> cardDao.insertCard(newcard));
}
Ah, ok donnera à votre solution un essai. Je devrais avoir la même instance Dao pour toutes les opérations de crud, corriger? Donc Supprimer () et UpdateCard () devraient également utiliser «CardDao ...», pas leur propre instance DAO unique?
Le toast a tiré, mais il a tiré deux fois à nouveau, même après avoir effectué une instance DAO pour insertion () et GetMax (). Voir le code révisé ci-dessus en fonction de votre réponse. D'abord, le toast a tiré et a déclaré que la carte précédente a été sauvée. Ensuite, il a tiré à nouveau et a dit que la dernière carte # a été sauvée. Donc, le deuxième toast ajusté correctement et montré le numéro de carte correct enregistré pour la dernière carte qui a été insérée dans la base de données. Mais le premier toast ne devrait pas tirer le feu car cette vision était précédemment enregistrée. Des idées pour résoudre le problème?
Les opérations de modèle d'affichage que vous appelez dans La mise en œuvre de par conséquent à la place, vous ne pouvez l'observer qu'une fois dans onclicksave code> sont asynchrones:
LivetaA code> enregistre la version de données ainsi que la dernière version vue par l'observateur. p>
insertcard code> commence à fonctionner sur un thread de travailleur pendant que vous commencez à observer
getmax code> du fil principal avec une nouvelle Observateur créé. Ainsi, vous recevrez la valeur actuelle ainsi que la nouvelle valeur après la mise à jour de la base de données. P>
Oncreate () Code> et attendez les mises à jour déclenché par la base de données: p>
Ah ok. Alors, comment puis-je limiter le toast pour ne être déclenché que par la méthode d'insertion (lorsqu'une carte de carte est ajoutée à la base de données) de sorte qu'elle ne se déclenche pas lorsque d'autres opérations de crud se produisent comme une méthode de suppression ou de mise à jour?
J'ai capturé le max existant dans la base de données, puis la comparé au maximum après la carte intégrée () pour déterminer qu'une nouvelle carte a été ajoutée. Réponse acceptée, upéted et Bounty attribuée. Santé à toi.
Question de suivi: Si je place l'observateur GetMax () dans l'Oncreate (), comment puis-je déterminer que la mise à jour a été déclenchée par la base de données? Je peux donc m'assurer que j'ouvre la dernière version non la version de données.
Je ne pense pas que getmax code> doit être utilisé pour déterminer l'exactitude de
insertcard code>. Vous devriez faire confiance à salle i> pour toujours renvoyer l'état correct de la base de données. Vous devez utiliser le résultat de l'appel d'insertion de la base de données pour vérifier si l'insertion a réussi.
OK, alors comment puis-je vous assurer que le code de vérification de l'insertion a été réussi à courir juste après l'insertion? Un clic bouton sur la touche "Enregistrer" exécute le code d'insertion. Juste après l'insertion, j'essaie de configurer des points de courant sur la carte pour des alarmes d'incendie ultérieures pour les notifications. J'essaie d'obtenir des données à partir de la carte nouvellement insérée (par exemple, carte.getid ()) pour configurer les dentifensants, mais je ne sais pas comment obtenir ces données dans le même bloc de code de "OnClickSave". J'apprécierais des idées ou des idées sur la manière de corriger.
Je suggérerais de poser une autre question. C'est trop d'informations pour répondre à un petit commentaire. N'hésitez pas à laisser un lien vers la nouvelle question ici.
Il n'y a pas `mviewmodel.insercard (carte1); `Méthode dans
ViewModel Code>. Partagez cette partie du code.
@Gensagames fera, par 18h et USA.
@Gensagames ViewModel Insert Card () a été mis à jour. Et le même pour le référentiel et le DAO.
Pouvez-vous déplacer le pain grillé à l'intérieur
ViewModel.get max (). Observez () code>? Votre toast pourrait-on tirer avant que les données ont été enregistrées et
newMax code> la valeur est mise à jour. @Ajw
@Prokash Sarkar Je comprends votre point mais je ne sais pas comment déplacer le toast à l'intérieur. Pouvez vous donner un exemple?
@Ajw comme ça?
mviewmodel.getmax (). Observez (ceci, valeur -> {newmax = valeur; toast.maketext (addorupdatexardactivity.Cette, "carte #" + newmax + "a été enregistré dans la liste", toast.longueur_long). ();}); code> cela garantit que le toast sera tiré lorsqu'un changement de données s'est produit dans la chambre.
@Prokash Sarkar ah, je vois. De cette façon Newmax est mis à jour et le toast est tiré après, oui?
@Ajw exactement! Faites-moi savoir si cela fonctionne.
@Prokash Sarkar ok donc j'ai déplacé "Msviewmodel.getmax ()." Code de l'ONCREATE () et le mettre juste en dessous "MVVueModel.insercard (Card1)". Le toast a tiré mais il a tiré deux fois. Tout d'abord, il a tiré et dit que la carte précédente était simplement enregistrée. Ensuite, il a tiré à nouveau et dit que la dernière carte # était juste sauvée. Ainsi, faire des progrès, car le deuxième toast ajusté correctement et montré le numéro de carte correct enregistré pour la dernière carte qui a été insérée dans la base de données. Mais le premier toast ne devrait pas tirer le feu car cette vision était précédemment enregistrée.
@Prokash Sarkar J'utilise également getmax () dans une autre activité pour observer le max de la base de données. Il y a peut-être un conflit avec les deux observateurs, c'est pourquoi il tire deux fois. Je vais re-nommer getmax () dans l'addorupdateCardactivity pour voir si cela résout le problème. Faites-moi savoir si vous avez d'autres idées sur la manière de résoudre.
@Ajw vous avez utilisé différentes dao instance i> pour insérer et observer. Ils doivent être identiques à toutes les opérations.
Donc, parce qu'il y a deux instances DAO, le toast tire deux fois?
@Prokash Sarkar Comment faire la même instance Dao? Modifiez l'instance DAO dans le référentiel pour observer pour correspondre à l'instance DAO de la tâche ASYNC pour INSERT?
@Ajw j'ai posté ma réponse. Faites-moi savoir si cela fonctionne.