【问题标题】:SQLite database in separate class vs. in same class, which is better? Android单独类中的 SQLite 数据库与同一类中的 SQLite 数据库,哪个更好?安卓
【发布时间】:2013-01-31 00:19:23
【问题描述】:

我有一个 SQLite 数据库,它与扩展 Activity 的主类不同。

我注意到有两种设置数据库的方法。一种方法是将它放在主 Activity 类中,无论是在类中还是作为嵌套的子类。第二种方法是放在单独的类中。

单独的类看起来更好,但是有一个缺点。每次你想做某事时,你都必须在主活动类中创建它的一个实例。我读到在 Android 中实例化对象很昂贵,应该避免。

尽管如此,我宁愿将数据库作为一个单独的类。实例化对象的成本是否足以让将数据库放在同一个类中更划算?

SQLite 数据库的单独类示例:不完整的伪代码

public class SQLiteDB {
   private static class DbHelper extends SQLiteOpenHelper{
      // db helper methods
   }

// methods for DB, like get, set, and others
public void openDatabase(){  }
public void closeDatabse(){  }
public void insertRecord(String record){  }
}

main Activity 中的示例使用:incompete psudo-code

public class Main extends Activity{

// every time I want to use it I must instantiate an object for the database class

// many instances of SQLiteDB object created, garbage collector works hard

SQLiteDB mDatabase = new SQLiteDB();

openDatabase();

insertRecord("insert this");

closeDatabase();

}

【问题讨论】:

  • 可以在onCreate()中实例化一次,在onDestroy()中关闭数据库。
  • 在内存使用和效率方面是否更好?在我的代码中多次实例化时?
  • 你不应该实例化一个新的 SQLiteDB 对象,你会请求已经设置好的数据库。你应该看看 SQLiteOpenHelper。使用该类,您请求获取当前数据库,以便您没有正在使用的多个不同数据库
  • @zabawaba 请注意,SQLiteDB 有一个扩展 SQLiteOpenHelper 的内部类。
  • @Kevik 你好,我添加了一些建议,看看吧。

标签: android database sqlite class instance


【解决方案1】:

SQLite 数据库在不同的类和在同一个类,哪个更好?

这是一个非常全面的问题,它取决于更多因素(应用程序类型、个人要求、您将如何处理 db 等)。有人可以更喜欢将数据库作为内部类而将某人作为单独的类。问题是许多开发人员试图将尽可能多的代码“粘贴”到一个类中,也许他们“害怕”创建更多的类。我不太清楚。我提到这只是作为我的个人笔记。

但让我们回到你的问题。什么是更好的?

我认为这种方法具有分隔类。你应该让你的活动类只有“活动类”> 只用于创建和处理 UI。应用程序外观应与应用程序逻辑分开。如果您遵循此“规则”,您的代码将变得更加干净和可读(如果其他人会查看您的代码,他不应该完全迷失方向)。有 20 节纯书面的课,所有的东西都粘在一个课上(就像一头猪一样),这并不可惜。

但是有一个缺点。你必须创建一个实例 每次您想做某事时,它都在主要活动类中。一世 读到在 Android 中实例化对象是昂贵的,应该是 避免。

你考虑过Singleton 的用法吗?这种设计模式值得思考。您将始终只有一个具有许多好处的实例,例如不浪费内存。我对单身人士只有很好的经验。因此,我建议您尝试使用它。

示例:

private static SQLiteOpenHelper instance;

public static SQLiteOpenHelper getInstance(Context mContext) {
   if (instance == null) {
      instance = new SQLiteOpenHelperImplementation(mContext);
   }
   return instance;
}

最后我给你一些建议:

  • 每次使用游标、数据库等时释放/关闭 他们在工作完成后立即。这样可以解决很多异常 与SQLiteDatabaseCursor相关

  • 使用同步块和方法是非常好的实践 在并发编程的情况下避免很多问题

  • 如果您在数据库中有多个表,我建议您创建 每个表的“服务”类将包装CRUD 操作和特定 表的方法

  • 在Activity被销毁之前,检查并释放所有未销毁的源 已经发布了。

【讨论】:

    【解决方案2】:

    我更喜欢您在此处提供的解决方案。主要优点是您可以轻松地从应用程序中的任何 Activity(或其他类)访问数据库。为了解决每次使用数据库都创建新实例的问题,可以改为在onCreate()中创建单个实例,在Activity处于活动状态时随意使用数据库,最后在onDestroy()中关闭数据库。

    【讨论】:

      【解决方案3】:

      这是个人喜好问题。

      但是,我发现创建一个扩展 SQLiteOpenHelper 的类是高效和干净的。在本课程中,您最终将编写 SQL 代码来创建表并将方法编写为存储过程。

      这个类看起来像这样:

      public class DatabaseInterface extends SQLiteOpenHelper {
      
      // Database version
      private static final int DATABASE_VERSION = 1;
      public DatabaseInterface(Context context) {
          super(context, DATABASE_NAME, null, DATABASE_VERSION);
      
      }
      //in your oncreate you will write the queries to create your tables
      @Override
      public void onCreate(SQLiteDatabase db) {
      
          String CREATE_NEWS = "CREATE TABLE News(id INTEGER)";
      
          db.execSQL(CREATE_NEWS);
      }
      
      // upgrading tables
      @Override
      public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
          // drop tables if exist
          db.execSQL("DROP TABLE IF EXSIST " + NEWS);
          // recreate tables
          onCreate(db);
      
      }
      

      假设我们有一个 News obj,它接受 1 个参数作为它的构造函数,您的存储过程可能看起来像这样:

      public ArrayList<News> getNews() {
          ArrayList<News> mNewes = new ArrayList<News>();
          SQLiteDatabase db = null;
          Cursor cursor = null;
      
          try {
              String sQry = "SELECT * FROM " + NEWS;
              db = this.getWritableDatabase();
              cursor = db.rawQuery(sQry, null);
      
              if (cursor.moveToFirst()) {
                  do {
                      mNewes.add(new News(cursor.getInt(0)));
      
                  } while (cursor.moveToNext());
              }
          } catch (SQLiteException e) {
              Log.e("SQLite - getNewes", e.getMessage());
              return null;
          } finally {
              cursor.close();
              db.close();
          }
      
          return mNewes;
      }
      

      在上述方法中,您获取并打开应用程序数据库,对其执行查询,预测任何 sql 错误,然后关闭数据库。这样做可以确保您永远不会打开任何您不需要/不使用的资源。

      我已经在两个目前在市场上销售的应用程序中使用了这种方法,它运行得相当快,对我为存储过程创建的方法进行了数百次调用

      【讨论】:

      • 如果您有 4-5 种类型的数据,您认为这样做是一个好的设计吗?例如,如果您的应用程序有 News、Aritcle、Author 和其他一些对象,那么数据库类将非常大,具有许多插入函数、许多更新函数等。
      • 就个人而言,我可能仍然会使用这种设计。但是,我可能会将实现分成不同的类,这样所有代码就不会在一个类中——可能是这样的吗? gist.github.com/zabawaba99/980ea292b305cbdd230a。您还可以最终使用适用于 android 的 ORM (sitepoint.com/5-best-android-orms),这会从您的终端中移除很多可能。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-18
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多