I am extracting a database using query, what is the best practice to store the data temporarily. Currently i am using ArrayList to hold the data extracted, but i am thinking that might not be best design practice.
Thanks
Cursor cur5 = database2.rawQuery("select ID from Quote where EmoticonID=? and SubCategoryID=?" ,new String [] {Integer.toString(gcid), Integer.toString(scid)});
if(cur5.getCount()==0){
Log.i("TAG Screen3", "No Quotes ID found for Particular ID");
if (helper2 != null) {
helper2.close();
}
if (database2 != null) {
database2.close();
}
}else{
cur5.moveToFirst();
do {
quoteid.add(Integer.parseInt(cur5.getString(0)));
Log.i("TAG Screen3 Quote ID", (cur5.getString(0)));
} while (cur5.moveToNext());
if(cur5 != null){
cur5.close();
}
if (helper2 != null) {
helper2.close();
}
if (database2 != null) {
database2.close();
}
}
Well if you already have a database to get the data from, why not using that database as temp store. Just get the data from the database when you need it an skip the temporary storage.
If you still want to store it locally on your phone I suggest a local sqlite database for huge objects or POJO's. If you have primitive types of key-value pairs you should use SharedPreferences.
For more information see http://developer.android.com/guide/topics/data/data-storage.html.
Or give us some information about your data and what you intend to do:) That might help us in helping you ;)
Related
I have a collection where I store user groups. Each group has a group name, group limit and an array of users ID's.
I wonder how the best way to retrieve one group details and then users details, like name, photo, etc.
Right now, I am doing two queries to the database. First retrieving the group data(name, etc), second getting a list of users who has in the user details the information of the group ID:
"syncDesp = a4sQ27xb1wuD2rhONU2K"
I'm afraid of calling the database to many times.
// Get Group details
Preferencias prefs = new Preferencias(view.getContext());
listenGroups = pFirestore.collection("syncDesps").document(prefs.getSyncDesp()).addSnapshotListener((documentSnapshot, e) -> {
if(e != null){
Log.i("dados erro", Objects.requireNonNull(e).getMessage());
}
if(documentSnapshot != null){
String nomeGrupo = Objects.requireNonNull(documentSnapshot.get("nomeGrupo")).toString();
textNomeGrupo.setText(nomeGrupo);
ArrayList membrosGrupo = (ArrayList) Objects.requireNonNull(documentSnapshot.get("syncDesp"));
}
});
// Get User Details
FirebaseFirestore grupoFire = FirebaseFirestore.getInstance();
grupoFire.collection("usuarios")
.whereEqualTo("syncDesp", prefs.getSyncDesp())
.addSnapshotListener((queryDocumentSnapshots, e1) -> {
listaUsuarios.clear();
if(e != null){
Log.i("dados erro", Objects.requireNonNull(e1).getMessage());
}
for(DocumentSnapshot usuarioSnapshot : Objects.requireNonNull(queryDocumentSnapshots).getDocuments()){
String idU = (usuarioSnapshot.get("id") == null) ? "" : Objects.requireNonNull(usuarioSnapshot.get("id")).toString();
String nomeUsuario = (usuarioSnapshot.get("nome") == null) ? "" : Objects.requireNonNull(usuarioSnapshot.get("nome")).toString();
String fotoUsuario = (usuarioSnapshot.get("imgUsuario") == null) ? "" : Objects.requireNonNull(usuarioSnapshot.get("imgUsuario")).toString();
UsuarioMeuGrupo usuarioMeuGrupo = new UsuarioMeuGrupo();//
usuarioMeuGrupo.setIdUsuario(idU);
usuarioMeuGrupo.setNome(nomeUsuario);
usuarioMeuGrupo.setFoto(fotoUsuario);
listaUsuarios.add(usuarioMeuGrupo);
}
adaptera.setOnItemClickRemoverListener(uMeuGrupo -> {
Log.i("dados uMeuGrupo Clic", uMeuGrupo.getNome());
});
adaptera.notifyDataSetChanged();
});
I wonder if I should query the group collection separately from the users collection or if there is a way of making only one function to retrieve data from both collections.
It's not possible to make a single query in Cloud Firestore span multiple collections. There is no join-like operation like you have in SQL. The only exception to this is collection group queries, which doesn't apply to your situation.
What you're doing right now is probably the best you can do with the database structure you have. If you want fewer queries, you'll have to do something to restructure your data to support that.
Does anyone know a way how to solve a problem?
I need to implement data storage with Realm.
I receive from network JSON object convert him to realm object Card and save it. I expand Card object with extra field favorite and change it manually from an application.
Every time when network operation executes insertOrUpdate wipes value, and insert throws an exception 'RealmPrimaryKeyConstraintException' because I have #PrimaryKey definition.
Is there exist in Realm feature how to use an insert with a particular update on Insert with Ignore?
Card card = realm.where(Card.class).equalTo(CardFields.ID, cardId).findFirst(); // https://github.com/cmelchior/realmfieldnameshelper
if(card == null) {
card = realm.createObject(Card.class, cardId);
}
card.setFavorite(true);
Or
Card card = realm.where(Card.class).equalTo(CardFields.ID, cardId).findFirst(); // https://github.com/cmelchior/realmfieldnameshelper
if(card == null) {
card = new Card();
card.setId(cardId);
}
card.setFavorite(true);
realm.insertOrUpdate(card);
Basically, if you don't want to overwrite the object, then you should query it and manipulate it, otherwise create it.
I'm developing an android app that uses SQLite as the local database. The app syncs data obtained from a web api and stores it in the local database. All the model classes have their ID property set as Primary key and Auto incremented so I can manually enter data without having to specify the ID. The issue is when I insert the data from the API into the SQlite, the ID of the object is ignored and Sqlite gives the object a new ID. I want the data stored with the same ID as the object being stored.
The web api returns the object lists that have their ID type long however the SQLite objects have their primary keys as int. Is this the reason why the ID values is not getting stored because their data types don't match? I can't change the datatype in my SQL database where the data comes from as there are hundreds of tables in it. Is there a way around it?
This is the Code to inserts or updates data in my local DB:
}
public async Task<string> insertUpdateVideoData(Video_Struct data)
{
try
{
var db = new SQLiteAsyncConnection(dbPath);
var m = GetVideos();
if (await db.FindAsync<Video_Struct>(f => f.VideoID == data.VideoID) != null)
{
await db.UpdateAsync(data);
}
else
{
if (await db.InsertAsync(data) != 0)
{
await db.UpdateAsync(data);
}
}
return "Single data file inserted or updated";
}
catch (SQLiteException ex)
{
return ex.Message;
}
}
This is the code to get data objects from the API:
public async Task<List<Video_Struct>> GetVideoData()
{
List<Video_Struct> vids = new List<Video_Struct>();
WebClient mClient = new WebClient();
var output = await mClient.DownloadDataTaskAsync(new Uri(GlobalVariables.host + "/api/media/getmedia"));
var json = Encoding.UTF8.GetString(output);
vids = JsonConvert.DeserializeObject<List<Video_Struct>>(json);
return vids;
}
If your local DB is a cache for web data and external DB gives you unique IDs, don't use auto increment in scheme, just re-use external IDs.
Actually, you can have a complex (compound) primary key, it depends on data unique properties.
If you do not work with your data as structured set you can try gson+SharedPreferences. Just don't forget to override equals and hashcode for your data models.
Datatype in not an issue, because sqlite uses INTEGER type.
I am new to android and maybe its a silly question but i am not getting it. See i am designing a game in which we give scores to some persons. So i want to store the names of the persons in a database while installation and then their scores set to 0 initially which will be updated according to what the users select. Here i am not able to figure out that how should i enter the data as it will be around 100 names and their scores. Using INSERT INTO() statement will make it like 100 statements. So is there any short method like can we do it through strings or something. Just guessing though. Any help would be appreciated.
You don't hard-code names or scores into your SQL statements. Instead, you use parameters.
var command = new SQLiteCommand()
command.CommandText = "INSERT INTO Scores (name, score) VALUES(#name, #score)";
command.CommandType = CommandType.Text;
foreach (var item in data)
{
command.Parameters.Add(new SQLiteParameter("#name", item.Name));
command.Parameters.Add(new SQLiteParameter("#score", item.Score));
command.ExecuteNonQuery();
}
and then just loop through all of the names and scores.
I recommend you using a transaction.
You can archive this stating you want to use a transaction with beginTransaction(), do all the inserts on makeAllInserts() with a loop and if everything works then call setTransactionSuccessful() to do it in a batch operation. If something goes wrong, on the finally section you will call endTransaction() without setting the success, this will execute a rollback.
db.beginTransaction();
try {
makeAllInserts();
db.setTransactionSuccessful();
}catch {
//Error in between database transaction
}finally {
db.endTransaction();
}
For the makeAllInserts function, something like this could work out:
public void makeAllInserts() {
for(int i = 0; i < myData.size(); i++) {
myDataBase = openDatabase();
ContentValues values = new ContentValues();
values.put("name", myData.get(i).getName());
values.put("score", myData.get(i).getScore());
myDataBase.insert("MYTABLE", nullColumnHack, values);
}
}
If you also want to know about the nullColumnHack here you have a good link -> https://stackoverflow.com/a/2663620/709671
Hope it helps.
It is said that we can retrieve our data if we are having objectId for that particular row, but it is auto generated and we cant insert it while setting data , so how to get data if i am not having object id , or any other means so that i can set objectId on my means.
Code is here as in comment:
ParseObject gameScore = new ParseObject("My Parse File");
String objectId = gameScore.getObjectId();
ObjectId doesnt't exist until a save operation is completed.
ParseObject gameScore = new ParseObject("My Parse File");
To retrieve the object id you need to save the object and register for the save callback.
gameScore.saveInBackground(new SaveCallback <ParseObject>() {
public void done(ParseException e) {
if (e == null) {
// Success!
String objectId = gameScore.getObjectId();
} else {
// Failure!
}
}
});
ObjectId can be retrieved from the original ParseObject(gameScore) once the done save callback is fired.
You can use this for getting current user object id
ParseUser pUser= ParseUser.getCurrentUser();
String objId= pUser.getObjectId();
not sure if this will apply to android , but I was trying to retreive the objectid, but for an entry that is already created. I did something like this and it worked.
ParseObject gameScore = new ParseObject("My Parse File");
var obId = gameScore.id;
Got it from the Javascript docs on Parse.com
The three special values are provided as properties:
var objectId = gameScore.id;
var updatedAt = gameScore.updatedAt;
var createdAt = gameScore.createdAt;
You can't unfortunately use the ObjectId until the object's been saved. I'm having this same problem now. The only solution I can think of, and posted a similar question relating to it here
My solution would be to make a tempId on the object and refer to that locally until it has an actual ObjectId, perhaps using a saveInBackground or saveEventually() callback to set other objects relating to it, to it's newly created ObjectId instead of it's old temp one.. when it's made available
It takes times for your values to be stored in table. Use this to get ObjectId
gameScore.saveInBackground(new SaveCallback() {
public void done(ParseException e) {
if (e == null) {
// Saved successfully.
Log.d("main", "User update saved!");
Log.d("main", "ObjectId "+gameScore.getObjectId());
} else {
// The save failed.
Log.d("main", "User update error: " + e);
}
}
});
In case you're handling the thread yourself:
First save:
gameScore.save();
Then you'll be able to access the id:
String parseId = gameScore.getObjectId();