I am trying to use ORMLite in my app (because apparently writing all the CRUD methods myself is the "harder not smarter" way to develop), but I am running into a problem: A lot of the sample projects I see have Activities that extend OrmLiteBaseActivity. Normally my Activities extend AppCompatActivity.
Is this going to be a problem at all? Does OrmLiteBaseActivity extend AppCompatActivity anywhere? Or do I have to sacrifice AppCompat if I go with ORMLite?
I'm not familiar with ORMLite however I wouldn't recommend dropping AppCompat in favor of ORMLite. So what can you do?
By looking at the source of ORMLiteBaseActivity you can see that this class extends Activity and not AppCompatActivity which basically makes sense for a library. Furthermore you can see that the class doesn't do much.
So Option #1 don't use the ORMLiteBaseActivity or Option #2 create an own Base Activity for your app which extends AppCompatActivity and does the same as the ORMLiteBaseActivity. In other words: It would be an option to copy the class in your project and to simply replace the extends part.
As for 2021, actually, you can do better. So you should not sacrifice AppCompatActivity for OrmLiteBaseActivity, you may use them both.
First, import OpenHelperManager:
import com.j256.ormlite.android.apptools.OpenHelperManager;
define object in your activity
private DatabaseHelper databaseHelper = null;
use following getHelperMethod
private DatabaseHelper getHelper() {
if (databaseHelper == null) {
databaseHelper = OpenHelperManager.getHelper(this, DatabaseHelper.class);
// we don't need the following line that much
// databaseHelper.getWritableDatabase(); // explicitly calls onCreate method of DatabaseHelper
//where you create tables for example, again it will be called anyway
}
return databaseHelper;
}
Override OnDestroy of your AppCompatActivity to free resources when your activity is done
#Override
protected void onDestroy() {
super.onDestroy();
if (databaseHelper != null) {
OpenHelperManager.releaseHelper();
databaseHelper = null;
}
}
So you may call any method of DatabaseHelper in my case listAllEntries() from your activity like this:
getHelper().listAllEntries();
Related
Hi I am kind of new to android, still learning. And my problem is that, for example I have a method which was created in the MainActivity and I need to call it from another class.
Is it a good practice to get the instance of the MainActivity so that I may be able to call the method in the MainActivity from another class?
This is an example:
public class MainActivity extends AppCompatActivity {
private static MainActivity inst;
public static MainActivity instances()
{
return inst;
}
#Override
public void onStart() {
super.onStart();
inst = this;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void showToast (String text){
Toast.makeText(inst, text, Toast.LENGTH_SHORT).show();
}
Then this is the other class:
public class broadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
MainActivity instance = new MainActivity();
instance.showToast(AnyText);
}
}
I saw this type of coding while looking at tutorials and wondered if it's a good practice or maybe there might be a better way? Since I get the warning of Do not place Android Context Classes in static classes
Thanks in advance for any insight or help! :D
I guess You want to make A singleton of Activity Class
but as Mention in All Pattern Design
using Singleton
If and Only If its only way to Make A Global Variable
Singleton is based on Lazing Initialing and Load On Memory
so I guess If you cant to Interact With Activiy You can Use
BroadCast Or Intents
You can call method from another class like this:
MainActivity instance = new MainActivity();
String data = instance.data();
and create data method in that class:
public String data() {
return mangaId;
}
Is it a good practice to get the instance of the MainActivity so that
I may be able to call the method in the MainActivity from another
class?
You totally can do this but you don't need to make it static and use a constructor. Just create a new instance like follows and you'll access the public methods
MainActivity mainActivity = new MainActivity();
mainActivity.showToast(text);
About the warning
It suggests avoiding having context fields defined as static. The warning itself explains why: It's a memory leak. If you make it static it will be accessible anywhere in your app and some methods can hold the reference to this context for a really long time and it won't be garbage collected. It will lead to a outofmemory exception and the app could crash. But here you're trying to invoke showToast() from broadcastreceiver so you can just get rid of static references. And it you need them in the future you safe ways to inject context
You cannot create instances of an Activity using the new operator.
You have to use an Intent to let an Activity to be created.
So you cannot get a reference to an instance of your activity.
The only methods you can use of your activity class are static ones.
I need to have an access to helper not only from Activities, but, for example, from BroadcastReceivers and AsyncTasks. Am I right, that if I am using OrmLiteBaseActivity to approach it is to use this methods:
OpenHelperManager.getHelper(context, DatabaseHelper.class);
OpenHelperManager.releaseHelper();
inside not Activity classes?
EDIT:
I understand that helper lifecycle is handled by OrmLiteBaseActivity. What I am asking is how to handle helper lifecycle outside of activities. For example, I need an access to database from BroadcastReceiver or AsyncTask. Is it a right way to achieve this using OpenHelperManager.getHelper(context, DatabaseHelper.class);, when I am starting some database stuff in another thread, and OpenHelperManager.releaseHelper();, when I've done all database work and want to release helper?
Am I right, that if I am using OrmLiteBaseActivity to approach it is to use this methods...
Yes, using the OpenHelperManager.getHelper(...) and releaseHelper() methods is the right way to do this. To quote from the ORMLite Android docs:
If you do not want to extend the OrmLiteBaseActivity and other base classes then you will need to duplicate their functionality. You will need to call OpenHelperManager.getHelper(Context context, Class openHelperClass) at the start of your code, save the helper and use it as much as you want, and then call OpenHelperManager.release() when you are done with it. You will probably want to have something like the following in your classes:
The sample code in the docs is:
private DatabaseHelper databaseHelper = null;
#Override
protected void onDestroy() {
super.onDestroy();
if (databaseHelper != null) {
OpenHelperManager.releaseHelper();
databaseHelper = null;
}
}
private DBHelper getHelper() {
if (databaseHelper == null) {
databaseHelper =
OpenHelperManager.getHelper(this, DatabaseHelper.class);
}
return databaseHelper;
}
I want to check if a SQLite Database is open, and if it is, I would like to access that Database within a service class.
I am worried, and have seen, that multiple open calls to the database clash, and throw exceptions. Because I do query the database within both my Activity and Service classes, I am attempting to implement the solution Commonsware recommended here: When to close db connection on android? Every time after your operation finished or after your app exit. However I do not want to close then open the Database within the Service class if the Activity might need it. From this answer Why use SQLiteOpenHelper over SQLiteDatabase?, it looks like it might make sense to implement a SQLiteOpenHelper to solve the issue of making multiple calls.
Thank you so much for all your help!!
This man Kevin is a legend: http://touchlabblog.tumblr.com/post/24474750219/single-sqlite-connection. Thank you so much.
On that link he shares his ridiculously simple solution:
public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
private static DatabaseHelper instance;
public static synchronized DatabaseHelper getHelper(Context context)
{
if (instance == null)
instance = new DatabaseHelper(context);
return instance;
}
//Other stuff...
}
Then in my SQLite class I changed my code to look like this:
public BlacklistWordDataSource(Context context) {
dbHelper = MySQLiteHelper.getHelper(context);
}
at onCreat in the activity put datasource.open();
then do what ever you want
and at the end of actevity put this to close :
/** Call after close activity */
#Override
protected void onStop() {
super.onStop();
//Close dataSource
datasource.close();
}
I am using the sample provided by James Morgan's DemoORMLiteAndroid which has one activity that instantiates a repository.
for reference
public class Repository {
private Dao<Room, Integer> roomDao;
public Repository(final DatabaseHelper databaseHelper) {
this.roomDao = getRoomDao(databaseHelper);
...
and in Activity
public class RoomActivity extends OrmLiteBaseListActivity<DatabaseHelper> {
private Repository repository;
#Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.repository = new Repository(getHelper());
}
...
this.repository.clearData();
...etc..
How should the repository be accessed in other activities or classes?
I'm not sure this a great answer #Kevin but here it goes.
ORMLite has a couple of base classes which help with the bootstrapping of the Android databases.
OrmLiteBaseActivity
OrmLiteBaseActivityGroup
OrmLiteBaseListActivity
OrmLiteBaseService
OrmLiteBaseTabActivity
Here are the Javadocs for them: http://ormlite.com/javadoc/ormlite-android/
All these base classes do is provide utility methods which help manage a DatabaseHelper class which extends OrmLiteSqliteOpenHelper. You only want one instance of the helper class since it manages the connection to the database which gets passed in with the onCreate() method.
The onCreate() method is what gets passed the Android SQLiteDatabase associated with the application which is needed for ORMLite to wrap inside its database connection code.
If you ask more specifically what you are trying to accomplish I'll edit my response to include more information.
I want to use a singleton pattern to hold a database and some other data/methods for my Android application.
I realize there are many reasons against singletons, but for this case I'd like to use it.
I've sub-classed UIApplication and made a data class within it called MyAppData.
MyAppData needs to have access to the SQLite database.
When I create the databse, I need to pass a context. I could pass the application context, but it will not directly relate to MyAppData.
I don't know if this wlll cause problems with my code.
So my thought is to have MyAppdata extend android.content.ContextWrapper. I don't think I should extend Activity because it's really not an activity, its a data class with methods to access the database.
I'm wondering if I extend ContextWrapper will there be something deep in the code I'm missing that will cause big problems down the road (memory leaks, etc).
This may not be the ideal approach to this (and I've considered other options), but my goal is to:
Have a singleton class in UIApplication that can encapsulate the database and be retrieved easily from any activity in my app.
Thanks in advance for your suggestions/warnings/advice.
Subclass android.database.sqlite.SQLiteOpenHelper and android.app.Application (with the latter being properly declared in AndroidManifest.xml).
Now,
public class MyApplication extends Application {
private static SQLiteOpenHelper openHelper;
#Override
public void onCreate() {
super.onCreate();
openHelper = new DbManager(this);
//
}
public static SQLiteDatabase getDB() {
return openHelper.getWritableDatabase();
}
}
Then have helper DAO classes that will perform instertions/updates/etc.
That's what I'm using in all of my apps.
I've used this approach:
Create a class responsible for managing the db, let's call it DBUtil. This class will extend android.database.sqlite.SQLiteOpenHelper. You can pass a reference to the application context to the constructor of this class. This class will contain methods for creating the db, adding, removing and retrieving items.
Create another class, let's call it AppCore, create a static instance of the DBUtil and a static init() method that accepts an ApplicationContext object
public class AppCore
{
public static var dbUtil:DBUtil;
public static void init( ApplicationContext context )
{
dbUtil = new DBUtil( context );
}
}
Then in the onCreate() method of our your application's main Activity, initialize the AppCore class.
#Override
protected void onCreate(Bundle savedInstanceState)
{
AppCore.init( getApplicationContext() );
}
So, it's not really a Singleton. Instead, the DBUtil instance is maintained as a static property, yet still accessible throughout your application, such as this:
AppCore.dbUtil.createNewRecord( params );
Also, I found this tutorial to be very helpful when getting started with this topic: http://developer.android.com/guide/tutorials/notepad/index.html