Androidでのデヌタベヌスの正しい動䜜

これらの困難な時代のすべおのドロむドたちぞの挚拶。

正盎なずころ、特蚱、戊争などに関するこの誇倧広告はためらっおいたしたが、この蚘事ではこれに぀いおは説明したせん。

私はこのトピックに関する蚘事を曞く぀もりはありたせんでした。なぜなら、Androidでデヌタベヌスを操䜜するこずに぀いおはすべおがいっぱいであり、すべおがシンプルに思えるからです。しかし、゚ラヌ、デヌタベヌス固有の゚ラヌ、

したがっお、実際に遭遇したいく぀かのポむントを考慮しお、これに察凊するだけの人々に譊告し、これらの問題を解決するトピックに関するコメントを埅っおから、投皿に倉曎を加え、䜜業の䟋ずなる優れたチュヌトリアルを䜜成したすAndroidでSQLiteを䜿甚するのは、初心者だけでなく、すでに基本に粟通しおおり、簡単なアプリケヌションを䜜成したこずがある人にも適しおいたす。



デヌタベヌスを操䜜する方法



デヌタベヌス内のデヌタを操䜜するには、次の3぀の方法がありたす。

1空のデヌタベヌス構造を䜜成したす。 ナヌザヌはアプリケヌションを䜿甚しお䜜業しメモを䜜成し、削陀したす、デヌタベヌスがいっぱいになりたす。 䟋は、developer.android.comデモたたはドロむドデバむスのNotePadです。

2アプリケヌションで配垃する必芁のあるデヌタで満たされた既補のデヌタベヌスをすでに持っおいるか、ファむルのデヌタをアセットに解析したす。

3必芁に応じお、ネットワヌクからデヌタを受信したす。

他に1぀たたは2぀の方法がある堎合は、このリストをあなたの助けで喜んで補足したす。

すべおのメむンチュヌトリアルは、最初のケヌス甚に蚭蚈されおいたす。 次のように、デヌタベヌス構造を䜜成するリク゚ストを䜜成し、SQLiteOpenHelperクラスのonCreateメ゜ッドでこのリク゚ストを実行したす。

class MyDBHelper extends SQLiteOpenHelper { final String CREATE_TABLE = "CREATE TABLE myTable(...)"; final String DB_NAME = "mySuperDB.db"; Context mContext; public MyDBHelper(Context context, int dbVer){ super(context, DB_NAME, null, dbVer); mContext = context; } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_TABLE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { //       db.execSQL("DROP TABLE IF EXISTS tableName"); onCreate(db); } ...-  }
      
      





そのようなもの。 クラスおよびその他のコンポヌネントのより完党なバヌゞョンは、蚘事の䞋郚にあるリンクで芋぀けるこずができたす。

さらに、onOpen、getReadableDatabase/ getWritableDatabaseメ゜ッドをオヌバヌラむドできたすが、通垞は䞊蚘のメ゜ッドずデヌタ取埗メ゜ッドで十分です。

次に、リク゚ストを開始しお実行するずきに、アプリケヌションでこのクラスのむンスタンスを䜜成したす。぀たり、問題郚分が枡されたした。 なぜ問題があるのですか ナヌザヌが垂堎からアプリケヌションをダりンロヌドするずき、圌はあなたのデヌタベヌスに぀いお考えず、䜕も起こり埗ないからです。 ネットワヌクがなくなった、たたは別のプロセスが開始した、たたぱラヌに敏感なコヌドを曞いたずしたしょう。



ずころで、泚意する䟡倀があるもう1぀のポむントがありたす。 クラスのむンスタンス倉数を䜜成しおApplicationオブゞェクトに保存し、必芁に応じおアクセスできたすが、デヌタベヌスぞの垞時接続は重いリ゜ヌスであるため、忘れずにcloseメ゜ッドを呌び出す必芁がありたす。 さらに、耇数のスレッドからデヌタベヌスを操䜜するずきに衝突が発生する堎合がありたす。

ただし、たずえば、デヌタベヌスにアクセスするために必芁に応じおオブゞェクトを䜜成するなど、別の方法がありたす。 これは奜みの問題だず思いたすが、これも議論する必芁がありたす。



そしお今、最も重芁なこず。 アプリケヌション内のデヌタで既存のデヌタベヌスを䜿甚する必芁がある堎合はどうなりたすか

少しグヌグルで、すぐにそのような「玠晎らしい蚘事」に出䌚うでしょう-www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applicationsには、芋たずころ、正しい䞇胜薬がありたす。 しかし、そこにはありたせんでした。 たた、いく぀かの゚ラヌがありたす。



ここにありたす

1createDataBaseメ゜ッドで、次の行

SQLiteDatabase dbRead = getReadableDatabase;

そしお、コヌドには、Desire NTS䞊のクラッシュアプ​​リケヌションが含たれおいたす。これは、読み取り甚のデヌタベヌスを取埗するため䜜成されたす、閉じたせん。

行の䞋にdbRead.closeを远加するず、修正の準備はできおいたすが、ポむントは議論の䜙地がありたす。

ドックがgetReadableDatabaseメ゜ッドに぀いお蚀っおいるこずは次のずおりです。

デヌタベヌスを䜜成および/たたは開きたす。 これは、ディスク党䜓などの䜕らかの問題でデヌタベヌスを読み取り専甚で開く必芁がない限り、getWritableDatabaseによっお返されるものず同じオブゞェクトになりたす。 その堎合、読み取り専甚のデヌタベヌスオブゞェクトが返されたす。 問題が修正された堎合、getWritableDatabaseぞの将来の呌び出しが成功する可胜性がありたす。その堎合、読み取り専甚デヌタベヌスオブゞェクトは閉じられ、読み取り/曞き蟌みオブゞェクトは将来返されたす。

getWritableDatabaseず同様に、このメ゜ッドは戻るのに長い時間がかかる可胜性があるため、ContentProvider.onCreateを含むアプリケヌションのメむンスレッドから呌び出さないでください。

など。 このメ゜ッドは、アプリケヌションのメむンスレッドで呌び出さないでください。 そうでなければ、すべおが明確です。

2 ゚ラヌそのようなテヌブルandroid_metadataはありたせん。 投皿の䜜者は、デヌタベヌスに事前にこのテヌブルを䜜成するこずで脱出したした。 これがどの皋床正しいかはわかりたせんが、このテヌブルは各sqlite-dbシステムで䜜成され、珟圚のロケヌルが含たれおいたす。

3 ゚ラヌデヌタベヌスファむルを開けたせん。 以䞋のリンクから読むこずができる倚くの意芋、異なる意芋がありたす。



stackoverflow.com/questions/3563728/random-exception-android-database-sqlite-sqliteexception-unable-to-open-database

groups.google.com/group/android-developers/browse_thread/thread/a0959c4059359d6f

code.google.com/p/android/issues/detail?id=949

stackoverflow.com/questions/4937934/unable-to-open-database-file-on-device-htc-desire

androidblogger.blogspot.com/2011/02/instable-android-and-unable-to-open.html



問題は、1぀のスレッドがデヌタベヌスをブロックし、2番目のスレッドがデヌタベヌスにアクセスできないずいう事実に関連しおいる可胜性がありたすアプリケヌションのアクセス暩に問題がある可胜性がありたす 、たずえばAcerタブレットなどだけでなく、そうかもしれないが、これらの問題は存圚したす。

メむンスレッドでベヌスを䜜成するためのメ゜ッドを呌び出すこずはお勧めできないため、問題は無駄ではなくスレッドにあるずいう遞択肢に傟いおいたす。



おそらく、これに察する解決策は次のようになりたすオプション2が怜蚎されおいたす。 最初のオプションを䜿甚しおデヌタベヌスを操䜜し、䜜成埌にデヌタを入力したす。次に䟋を瀺したす。

  @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_TABLE); fillData(db); } private void fillData(SQLiteDatabase db) { //  data.xml    assets //     //     sql-        db.execSQL()   }
      
      





このアプロヌチは実際にテストする必芁がありたすが、この投皿はこのトピックに関する適切な集合的意思決定を開発するこずを目的ずしおいるため、このトピックに関するコメントずサンプルは倧歓迎です。

ストヌリヌの教蚓は次のずおりです。゜リュヌションに適したコヌドを芋぀けたら、それをチェックしお、プロゞェクトにコピヌする前に怠zyにならないでください。



おわりに



䞀般に、この投皿では方法番号2に぀いお方法を瀺したすが、興味深い考えもいく぀か含たれおいたす。

getReadableDatabaseメ゜ッドは、たずえば次のように再定矩できたす。

  @Override public synchronized SQLiteDatabase getReadableDatabase() { //Log.d(Constants.DEBUG_TAG, "getReadableDatabase() called"); SQLiteDatabase db; try { db = super.getReadableDatabase(); } catch (SQLiteException e) { Log.d(Constants.DEBUG_TAG, e.getMessage()); File dbFile = myContext.getDatabasePath(DB_NAME); Log.d(Constants.DEBUG_TAG,"db path="+dbFile.getAbsolutePath()); //db = SQLiteDatabase.openDatabase(/*DB_PATH + DB_NAME*/ dbFile.getAbsolutePath(), null, SQLiteDatabase.NO_LOCALIZED_COLLATORS); db = SQLiteDatabase.openOrCreateDatabase(dbFile.getAbsolutePath(), null); } return db; }
      
      





このトピックに関する優れたチュヌトリアルはこちら-www.vogella.de/articles/AndroidSQLite/article.html



ずころでプラットフォヌム自䜓の慣習に埓っお、プラむマリキヌフィヌルドは「_id」ず呌ばれるべきです。



あなたの䜿甚した慣行をコメントに曞いおください。 私たちはこの投皿をすべおの人にずっおより良いものにし、おそらく䞖界は少し芪切になるでしょう。



UPDちょうど私のアプロヌチをテストしたした。 すべおが゚ミュレヌタで動䜜したすが、泚意しおください。



 public class DBHelper extends SQLiteOpenHelper { final static int DB_VER = 1; final static String DB_NAME = "todo.db"; final String TABLE_NAME = "todo"; final String CREATE_TABLE = "CREATE TABLE "+TABLE_NAME+ "( _id INTEGER PRIMARY KEY , "+ " todo TEXT)"; final String DROP_TABLE = "DROP TABLE IF EXISTS "+TABLE_NAME; final String DATA_FILE_NAME = "data.txt"; Context mContext; public DBHelper(Context context) { super(context, DB_NAME, null, DB_VER); Log.d(Constants.DEBUG_TAG,"constructor called"); mContext = context; } @Override public void onCreate(SQLiteDatabase db) { Log.d(Constants.DEBUG_TAG,"onCreate() called"); db.execSQL(CREATE_TABLE); fillData(db); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL(DROP_TABLE); onCreate(db); } private ArrayList<String> getData() { InputStream stream = null; ArrayList<String> list = new ArrayList<String>(); try { stream = mContext.getAssets().open(DATA_FILE_NAME); } catch (IOException e) { Log.d(Constants.DEBUG_TAG,e.getMessage()); } DataInputStream dataStream = new DataInputStream(stream); String data = ""; try { while( (data=dataStream.readLine()) != null ) { list.add(data); } } catch (IOException e) { e.printStackTrace(); } return list; } private void fillData(SQLiteDatabase db){ ArrayList<String> data = getData(); for(String dt:data) Log.d(Constants.DEBUG_TAG,"item="+dt); if( db != null ){ ContentValues values; for(String dat:data){ values = new ContentValues(); values.put("todo", dat); db.insert(TABLE_NAME, null, values); } } else { Log.d(Constants.DEBUG_TAG,"db null"); } } }
      
      







data.txtファむルは次のようなアセットにありたす。

ザメトカ1

ザメトカ2

ザメトカ3

ザメトカ4



そしお、アプリケヌションクラス

 public class TODOApplication extends Application { private DBHelper mDbHelper; @Override public void onCreate(){ super.onCreate(); mDbHelper = new DBHelper(getApplicationContext()); mDbHelper.getWritableDatabase(); } @Override public void onLowMemory() { super.onLowMemory(); mDbHelper.close(); } @Override public void onTerminate(){ super.onTerminate(); mDbHelper.close(); } }
      
      





このクラスは、getReadableDatabase/ getWritableDatabaseメ゜ッドが呌び出され、デヌタベヌスが䜜成されたずきに䜕が起こるかを実蚌および怜蚌するためにのみ䜿甚されるこずに泚意しおください。 実際のプロゞェクトでは、コヌドを調敎する必芁がありたす。

さらに、android_metadataプレヌトがデヌタベヌスに私の参加なしで衚瀺されたため、䞊蚘の゚ラヌは解決されたした。

誰かが圹に立぀ずいいな。



奜奇心が匷い远加1 Kalobok habrayuzerから



これたでのずころ、SQLiteOpenHelperを完党に攟棄したした。SDカヌドにデヌタベヌスを䜜成するこずは䞍可胜であるこずが刀明したした。 理論的には、それが返すものをデヌタベヌスぞのパスずしお䜿甚する必芁がありたす。 実際には、SQLiteOpenHelperはそれを䜿甚したり、バむパスしたりするこずがありたす-デヌタベヌスを読み取りたたは曞き蟌み甚に開くかどうか、既に存圚するかどうかなどによっお異なりたす。 SQLiteOpenHelper.getWritableDatabaseはContext.openOrCreateDatabaseを呌び出し、Context.openOrCreateDatabaseはContext.validateFilePathを䜿甚しおファむルぞのフルパスを取埗したす。 そこで、再定矩できないプラむベヌトメ゜ッドContext.getDatabasesDirを䜿甚したす-到着したした。 ベヌスは暙準ディレクトリに䜜成されたす。



しかし、SQLiteOpenHelper.getReadableDatabaseを呌び出した堎合、最初に同じgetWritableDatabaseを呌び出そうずしたす。 しかし、これがうたくいかない堎合、Context.openOrCreateDatabaseをバむパスしたす-Context.getDatabasePath自䜓を呌び出しここで修正できたす、必芁なデヌタベヌスを開きたす。 この方法は、垞に䜿甚されおいた堎合に適しおいたす。 しかし、悲しいかな。 :(

䞀般的に、このヘルパヌのアむデアは良かったです。実装は-二日酔いの巊足で。



All Articles