46 : اندرويد : تخزين المعطيات والبحث ضمنها Storing and Searching for Data

 

ملاحظة : الموضوع عبارة عن حلقة من حلقات سلسلة برمجة وتطوير اندرويد Android Development

اندرويد :   تخزين المعطيات والبحث ضمنها  Storing and Searching for Data

السلام عليكم ورحمة الله وبركاته

 سوف نتعلم ضمن هذا الدرس ما يلي:

  1. إنشاء الجدول الافتراضي Create the Virtual Table
  2. تعبئة الجدول الافتراضي بالمعطيات Populate the Virtual Table
  3. البحث عن الاستعلام Search for the Query

هنالك عدة طرق لكي تخزن بها معطياتك, مثل تخزينها ضمن قاعدة معطيات اونلاين online database , او ضمن قاعدة معطيات محلية local SQLite database, او حتى ضمن ملف نصي.

القرار راجع لك لكي تقرر الحل الافضل الذي يناسب تطبيقك.

ضمن هذا الدرس سوف نبين لك كيف تنشأ جدول SQLite  افتراضي , الذي بدوره يستطيع ان يزودك بآليات بحث نصية قوية ومتكاملة.

يتم ملأ الجدول بالمعطيات من ملف نصي يحوي على ثنائيات من  “كلمة ” و”تعريفها” ضمن كل سطر من اسطر الملف.

إنشاء الجدول الافتراضي Create the Virtual Table

يتصرف الجدول الافتراضي بشكل مشابه لجدول SQLite, ولكنه يقرأ ويكتب الاغراض ضمن الذاكرة عبر الاستدعاءات callbacks, بدل من كتابتها او قرائتها ضمن ملف قاعدة المعطيات.

لكي ننشأ جدول افتراضي, نقوم بإنشاء صف لهذا الجدول:

public class DatabaseTable {
    private final DatabaseOpenHelper mDatabaseOpenHelper;

    public DatabaseTable(Context context) {
        mDatabaseOpenHelper = new DatabaseOpenHelper(context);
    }
}

أنشأ صف داخلي ضمن الصف DatabaseTable, الذي بدوره يقوم ب extends  للصف SQLiteOpenHelper.

يقوم الصف SQLiteOpenHelper يتعريف التوابع المجردة  abstract methods  التي يتوجب عليك ان تقوم ب Override  لها , وبذلك يصبح بالامكان انشاء جدولك الافتراضي وتحديثه عند الحاجة.

على سبيل المثال, فيما يلي بعض الرماز الذي يقوم بالتصريح عن جدول لقاعدة المعطيات الذي بدوره سوف يحوي على كلمات لتطبيق القاموس:

public class DatabaseTable {

    private static final String TAG = "DictionaryDatabase";

    //The columns we'll include in the dictionary table
    public static final String COL_WORD = "WORD";
    public static final String COL_DEFINITION = "DEFINITION";

    private static final String DATABASE_NAME = "DICTIONARY";
    private static final String FTS_VIRTUAL_TABLE = "FTS";
    private static final int DATABASE_VERSION = 1;

    private final DatabaseOpenHelper mDatabaseOpenHelper;

    public DatabaseTable(Context context) {
        mDatabaseOpenHelper = new DatabaseOpenHelper(context);
    }

    private static class DatabaseOpenHelper extends SQLiteOpenHelper {

        private final Context mHelperContext;
        private SQLiteDatabase mDatabase;

        private static final String FTS_TABLE_CREATE =
                    "CREATE VIRTUAL TABLE " + FTS_VIRTUAL_TABLE +
                    " USING fts3 (" +
                    COL_WORD + ", " +
                    COL_DEFINITION + ")";

        DatabaseOpenHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
            mHelperContext = context;
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            mDatabase = db;
            mDatabase.execSQL(FTS_TABLE_CREATE);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
                    + newVersion + ", which will destroy all old data");
            db.execSQL("DROP TABLE IF EXISTS " + FTS_VIRTUAL_TABLE);
            onCreate(db);
        }
    }
}

تعبئة الجدول الافتراضي Populate the Virtual Table

الجدول الآن بحاجة لمعطيات ليقوم بتخزينها.

الترميز التالي يبين لك كيف بإمكانك ان تقوم بالقراءة من ملف نصي (located in res/raw/definitions.txt)  يحوي على الكلمات وتعريفاتها, كيفية المرور على الملف , وكيفية ادخال كل سطر من اسطر الملف كسطر ضمن الجدول الافتراضي.

يتم انجاز ذلك كله ضمن thread اخر وذلك لمنع حجب وقفل واجهة المستخدم UI locking.

اضف الرماز التالي إلى الصف الداخلي DatabaseOpenHelper .

ملاحظة : قد ترغب ايضا استدعاء callback لتنبيه واجهات المستخدم الخاصة بفعاليتك عند انتهاء هذا ال thread  من عمله.

private void loadDictionary() {
        new Thread(new Runnable() {
            public void run() {
                try {
                    loadWords();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();
    }

private void loadWords() throws IOException {
    final Resources resources = mHelperContext.getResources();
    InputStream inputStream = resources.openRawResource(R.raw.definitions);
    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

    try {
        String line;
        while ((line = reader.readLine()) != null) {
            String[] strings = TextUtils.split(line, "-");
            if (strings.length < 2) continue;
            long id = addWord(strings[0].trim(), strings[1].trim());
            if (id < 0) {
                Log.e(TAG, "unable to add word: " + strings[0].trim());
            }
        }
    } finally {
        reader.close();
    }
}

public long addWord(String word, String definition) {
    ContentValues initialValues = new ContentValues();
    initialValues.put(COL_WORD, word);
    initialValues.put(COL_DEFINITION, definition);

    return mDatabase.insert(FTS_VIRTUAL_TABLE, null, initialValues);
}

قم باستدعاء التابع loadDictionary()  في الوقت المناسب لتملأ الجدول بالمعلومات المناسبة.

المكان المناسب لهذا الاستدعاء ضمن التابع onCreate()ضمن صف DatabaseOpenHelper , وذلك فورا بعد انشاء الجدول:

@Override
public void onCreate(SQLiteDatabase db) {
    mDatabase = db;
    mDatabase.execSQL(FTS_TABLE_CREATE);
    loadDictionary();
}

البحث عن الاستعلام Search for the Query

ما ان يصبح لديك الجدول الافتراضي بعد انشاءه وتعبيئته بالمعطيات, استخدم الاستعلام المزود من قبل SearchView  للبحث عن المعطيات.

اضف التوابع التالية إلى الصف DatabaseTable  لبناء عبارة SQL التي تقوم بالبحث عن الاستعلام:

 

public Cursor getWordMatches(String query, String[] columns) {
    String selection = COL_WORD + " MATCH ?";
    String[] selectionArgs = new String[] {query+"*"};

    return query(selection, selectionArgs, columns);
}

private Cursor query(String selection, String[] selectionArgs, String[] columns) {
    SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
    builder.setTables(FTS_VIRTUAL_TABLE);

    Cursor cursor = builder.query(mDatabaseOpenHelper.getReadableDatabase(),
            columns, selection, selectionArgs, null, null, null);

    if (cursor == null) {
        return null;
    } else if (!cursor.moveToFirst()) {
        cursor.close();
        return null;
    }
    return cursor;
}

يتم البحث عن الاستعلام عبر استدعاء التابع getWordMatches().اي نتائج مطابقة سوف يتم اعادتها ضمن Cursor  التي بإمكانك التجوال ضمنها او استخدامها لبناء ListView.

يقوم هذا المثاال باستدعاء التابع getWordMatches()  ضمن تابع handleIntent()  الخاص بفعالية البحث searchable activity.

تذكر بأن فعالية البحث تتلقى الاستعلام ضمن intent ACTION_SEARCH  عبر ال extra, وذلك بسبب ال intent filter  الذي قمت بإنشاءه مسبقا:

DatabaseTable db = new DatabaseTable(this);

...

private void handleIntent(Intent intent) {

    if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
        String query = intent.getStringExtra(SearchManager.QUERY);
        Cursor c = db.getWordMatches(query, null);
        //process Cursor and display results
    }
}

وإلى لقاء قريب في الحلقة المقبلة

وإلى ذلك الحين استودعكم الله والسلام عليكم ورحمة الله وبركاته

Advertisements

, , , , ,

  1. أضف تعليق

اترك رد

Please log in using one of these methods to post your comment:

WordPress.com Logo

أنت تعلق بإستخدام حساب WordPress.com. تسجيل خروج   / تغيير )

صورة تويتر

أنت تعلق بإستخدام حساب Twitter. تسجيل خروج   / تغيير )

Facebook photo

أنت تعلق بإستخدام حساب Facebook. تسجيل خروج   / تغيير )

Google+ photo

أنت تعلق بإستخدام حساب Google+. تسجيل خروج   / تغيير )

Connecting to %s

%d مدونون معجبون بهذه: