آموزش اندروید-فصل ۲۶: پایگاه داده در اندروید (قسمت چهارم)

در سه مطلب قبلی (اینجا و اینجا و اینجا) درباره دیتابیس یا پایگاه داده در اندروید نوشتم. در این مطلب می‌خواهم درباره جنبه‌های پیشرفته‌تری از پایگاه داده صحبت کنم. برای کار همان مثال قبلی که درباره Person بود را ادامه می‌دهم. البته همزمان با امکانات پیشرفته‌تری از اندروید و لیست ویو هم آشنا خواهید شد.

جستجو

نمایش لیستی از اشیا همواره چیزی نیست که می‌خواهیم. گاهی اوقات دوست داریم اطلاعات نمایش داده شده را بر اساس بعضی ویژگی‌ها فیلتر کنیم و فقط بخشی از اطلاعات را نمایش دهیم. برای این کار باید در پایگاه داده جستجو کنیم یه به عبارت دقیق‌تر کوئری‌های خود را محدودتر کنیم تا فقط اطلاعاتی که می‌خواهیم را به ما برگرداند.

برای شروع یک ادیت تکست EditText به بالای صفحه لیست Person اضافه می‌کنیم. به محض این که کاربر شروع به تایپ در این ادیت تکست بکند، اطلاعات نمایش داده شده در لیست فیلتر شده و فقط اسامی‌ای را نمایش می‌دهد که مشابه متن وارد شده توسط کاربر هستند. برای شروع به سراغ فایل layout می‌رویم:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <EditText
        android:id="@+id/filterEditText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <ListView
        android:id="@+id/personListView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>
</LinearLayout>

همانطور که می‌بینید طراحی صفحه را تغییر داده و یک چیدمان خطی یا LinearLayout را به عنوان ویوی اصلی قرار داده و داخل آن یک EditText و ListView قرار دادیم.

حالا به سراغ اکتیویتی می‌رویم. اولین کاری که می‌کنیم تعریف کردن یک ادیت تکست و find کردن آن است (به نظرم دیگر به سطحی رسیده‌اید که لازم نباشد در هر مرحله تغییرات این چنینی در کد را ننویسم!)

حالا باید کاری بکنیم که هر بار که کاربر چیزی در ادیت تکست وارد می‌کند ما بفهمیم و لیست را بر اساس آن فیلتر کنیم.

(در پرانتز می‌گویم که ساده‌تر بود در جلوی ادیت تکست یک دکمه می‌گداشتیم تا کاربر با کلیک کردن بر روی آن جستجو را انجام دهد اما می‌خواهم با یک تیر چند هدف بزنم: جستجو را یاد بگیرید، یاد بگیرید که چطور حرفه‌ای‌تر با EditText کار کنید و از نوشتن برنامه‌ای حرفه‌ای‌تر لذت ببرید!)

برای فهمیدن تغییرات ادیت تکست آن هم درست در زمانی که کاربر شروع به نوشتن در آن می‌کند از TextWatcher استفاده می‌کنیم:

filterEditText.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }

    @Override
    public void afterTextChanged(Editable s) {
    }
});

حالا هر زمان که کاربر متن داخل ادیت تکست را تغییر دهد بلافاصله از طریق این تکست واچر مطلع می‌شویم. هر کدام از این سه تابع نوع حاصی از تغییر را به ما اطلاع می‌دهند. در حال حاضر وارد جزئیات TextWatcher نمی‌شویم. متدی که ما لازم داریم afterTextChanged است:

@Override
public void afterTextChanged(Editable s) {
    search(s.toString());
}

با این کار به برنامه می‌گوییم با هر تغییری که کاربر در متن ادیت تکست وارد می‌کند، متد search صدا زده شود. حالا متدی با نام search در اکتیویتی ایجاد می‌کنیم:

private void search(String s) {
}

فعلاً اکتیویتی را رها کرده و به سراغ PersonDatabaseAdapter می‌رویم. باید تابعی بنویسیم که عبارت جستجو را گرفته و لیستی از Person به ما برگرداند که شرایط جستجو را داشته باشند. برای این کار تابع readAllPersons را تغییر می‌دهیم تا نیازی به دوباره کاری و تکرار این همه کد نداشته باشیم:

public ArrayList<Person> readAllPerson(String search) {
    //...
}

حالا باید اول کار چک کنیم آیا کاربر متنی را برای جستجو فرستاده است یا نه:

// ...
String[] columns = new String[]{"id", "name", "family"};
String selection = null;
String[] selectionArgs = null;
String groupBy = null;
String having = null;
String orderBy = null;
String limit = null;

if( search != null && !search.isEmpty()) {

}

حالا اگر کاربر چیزی را برای جستجو فرستاده باشد، کمی دستکاری در این متغیرها کار ما را راه می‌اندازد:

if( search != null || !search.isEmpty()) {
    selection = "name LIKE ? OR family LIKE ?";
    selectionArgs = new String[] {search + "%", search + "%"};
}

با این کار جستجو را محدود به مواردی می‌کنیم که name یا family آن‌ها یا search شروع می‌شود.

حالا برمی‌گردیم به اکتیویتی. اول به خاطر تغییری که در امضای متد readAllPersons دادیم باید خط زیر را اصلاح کنیم:

persons = databaseAdapter.readAllPerson();

در این مثال ما می‌خواهیم اول همه رکوردها را نمایش داده و بعد بر اساس متنی که کاربر وارد می‌کند آن را فیلتر کنیم. بنابراین کافی است null را به این تابع بفرستیم تا همه چیز مثل قبل کار کند:

persons = databaseAdapter.readAllPerson(null);

حالا می‌رویم سراغ متد search. به نظرم از اینجای کار را می‌توانید حدس بزنید: تابع readAllPersons را با مقداری که کاربر وارد کرده صدا می‌زنیم و لیست Person های برگشتی را می‌دهیم به لیست ویو برای نمایش:

private void search(String s) {
    persons = databaseAdapter.readAllPerson(s);
    PersonListAdapter personListAdapter = new PersonListAdapter(persons, this);
    personListView.setAdapter(personListAdapter);
}

تبریک می‌گم! حالا ما یک برنامه داریم که واقعاً در دیتابیس جستجو می‌کند. برای امتحان چند اسم و فامیل در دیتابیس ذخیره می‌کنیم و بعد به سراغ لیست می‌رویم:

ch26-database-1

حالا به محض این که شروع به تایپ کردن بکنید می‌بینید لیست کوچکتر و کوچکتر می‌شود:

ch26-database-2

با دیتابیس کارهای زیادی می‌شود انجام داد اما من در همین جا مطلب دیتابیس را می‌بندم و در مطلب بعدی به سراغ خود لیست ویو می‌روم!

کد کامل پروژه  را در گیت‌هاب اسمارت‌لب آپلود کردم: دانلود کد از گیت‌هاب

راستی چرا کانال اسمارت‌لب در تلگرام را دنبال نمی‌کنید؟

29 فکر می‌کنند “آموزش اندروید-فصل ۲۶: پایگاه داده در اندروید (قسمت چهارم)

  1. رضا

    سلام خیلی خوبه… اما لطفا سورس تمام شده سرچ را در دیتابیس ، در آخر همین مطلب قرار بدین چون خیلی تکه تکه هستند کد ها و کمی گیج کننده اس!
    بازم ممنون بابت زحماتتون

    پاسخ
  2. علی رضا

    سلام
    اول از همه ممنون بابت به اشتراک گذاشتن آموزش های اندروید. خسته نباشید.
    دوم اینکه یه سوال دارم که متاسفانه ربطی به موضوع بالا نداره ولی سایت رو گشتم و پستی مربوط به زبان ندیدم که اونجا سوالم رو بپرسم.
    وقتی که layout فارسی رو به برنامه اضافه میکنم همه چیز خود به خود راست به چپ میشه که عالیه. اما من نیاز دارم که مثلا یه vertical linear layout با متعلقات داخلش توی صفحم راست به چپ نشه و توی همون فرم انگلیسی که تعریف کردم بمون. چطور باید این رو از بقیه جدا کنم؟

    پاسخ
    1. علی بهزادیان نژاد نویسنده

      سلام
      سپاسگزارم از محبتتون.
      برای اون لی‌اوت خطی عمودی که می‌خواید محتویاتش چپ چین بمونه ویژگی android
      :gravity=”left” رو تعریف کنید.

      پاسخ
  3. حسین

    آموزش ها عالیه. تازه از طراحی سایت دارم میام سمت اندروید و امروز کار با دیتابیس رو به کمک سایت شما و چند تا سایت خارجی دیگه یاد گرفتم. منتظر مطالب آموزشی دیگه هم هستم. ترجیحا کار با ویوهای متریل دیزاین!

    راستی راهی هست که بتونیم از سایت شما حمایت مالی کنیم که زودتر آموزش بذارید؟

    پاسخ
    1. علی بهزادیان نژاد نویسنده

      سلام. متشکرم بابت لطف شما. درباره حمایت هم همین نظرات ارزشمند شما بهترین حمایت از اسمارت‌لب است. سپاسگزارم.

      پاسخ
  4. امیر

    سلام
    سوالی داشتم که اگر بتونین راهنماییم کنین خیلی ممنون میشم ازتون
    اینکه یه برنامه اندروید شبیه مخاطبین تلفن ساختم که عملیات هایی مثل حذف کردن،ایجاد و ویرایش کردن مخاطبین رو انجام میده
    این نرم افزار روی گوشی جواب داد اما هدف من اینه که بعد از خروجی گرفتن از برنامه به صورت apk از قبل یه سری اطلاعات هم در دیتابیس موجود باشه و نشون بده
    “یعنی حفظ اطلاعات دیتابیس در ضمن خروجی گرفتن از برنامه” بدون اینکه بخوام از دیتابیس های از پیش ساخته توسط نرم افزار های مختلف استفاده کنم و توسط اندروید استادیو فراخونیشون کنم!
    چون در حالت عادی برای این منظور هر دیوایسی یه دیتابیس داره که جدول هاش خالی از هر گونه اطلاعات هستش که هر کاربری فقط خودش باید حذف و اضافه و ویرایش کردن و … رو انجام بده
    با تشکر

    پاسخ
  5. ابوذر

    سلام
    نمیدونم چی بگم … هر چی بگم کم گقتم … واقعا عالی بود
    خیلی ساده و روان توضیح داداه بودید … بابت زحماتی که کشیدید ازتون متشکرم

    پاسخ
    1. علی بهزادیان نژاد نویسنده

      دوست دارم مطالب بیشتری بنویسم ولی چند وقت اخیر به شدت سرم شلوغه و فرصتی برای نوشتن ندارم. انشاالله از این هفته یک کار نو رو شروع می‌کنم تو اسمارت‌لب که احتمالا به درد خیلی‌ها می‌خوره 🙂

      پاسخ
  6. kavianik

    سلام.وقتتون بخیر.
    برای یک بخشی،نیاز دارم که برنامه طوری باشه که هر کاربر بتونه پست ثبت کنه و کاربرهای دیگه بتونن زیر پست مورد نظرشون،نظرشونو ثبت کنن.
    گویا باید از دیتا بیس استفاده کنم.
    الان ینی هم ثبت پست و نظر برام سواله و هم ارتباطشون که بگم این نظر برای کدوم پسته.

    پاسخ
  7. middle

    سلام وقت بخیر …
    بسیار ممنونم به خاطر این مطالبی که میزارید واقعا خیلی مفید بودن برام
    توی بیشتر سایتا گشتم یکی از بهترین و کامل ترین مطالب در مورد پایگاه داده ها در آندروید بود …
    فقط اگ میشه حذف رکورد رو هم بگین چجوریه .. چون آخه من هر کاری میکنم رکورد حذف نمیشه ..
    یک ادیت تکست با یک دکمه اضافه کردم، توی ادیت تکست آیدی رکورد وارد میکنم بعد توی کد دکمه به لانگ تبدیلش میکنم و به تابع دلیت ارسالش میکنم ولی بازم لیست رو میبینم رکورد حذف نشده .. اگ میشه این مشکل رو برام حل کنید واقعا خیلی برام مهمه …مرسی

    پاسخ
        1. علی بهزادیان نژاد نویسنده

          بستن برنامه به معنای نابود شدن برنامه نیست. بهتره تابعی برای رفرش کردن لیست بنویسید.

          پاسخ
  8. مهدی

    سلام
    چطوری میتونیم به edit text قابلیت تشخیص زبان ورودی رو اضافه کنیم؟
    ینی اگر متن ورودی انگلیسی بود یک سری متد هارو اجرا کنه
    وقتی که فارسی بود متد های دیگری رو اجرا کنه

    پاسخ
    1. علی بهزادیان نژاد نویسنده

      سلام
      برای کنترل یک EditText وقتی که کاربر شروع می‌کند به وارد کردن متن، از کلاس TextWatcher استفاده کنید.
      در همین فصل مثالی از استفاده از این کلاس آمده است. کاراکتری را که کاربر وارد می‌کند چک کنید و ببینید آیا در محدوده یونیکد فارسی قرار دارد یا نه و بعد به تناسب کار دلخواه خودتان را انجام دهید.

      پاسخ
  9. بابک

    سلام خیلی ممنون از اموزشاتون واقعا مفید بودن
    سوالم اینه که برا پاک کردن item از همین دیتا بیس و listAll چطوری باید عمل کرد
    هر کاری کردم نشد

    پاسخ
  10. عرفان

    سلام و وقت به خیر.
    یک سوال داشتم از خدمت تون. من براش OnItemClickListener برای رفتن به مطلب مورد نظر تعریف کردم اما برای تمام مطالب فقط اولین متن رو باز می کنه، چجوری درستش کنم
    با تشکر از مطالب بسیار خوب و کاربردی

    پاسخ
      1. عرفان

        ممنون از توجه تون/ به دو صورت امتحان کردم که از هردو همان نتیجه رو گرفتم.

        .setOnItemClickListener(
        new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView parent, View view,
        int position, long id)
        {
        Intent intenet = new Intent(getBaseContext(), DeatailsActivity.class);
        String res_id = resultBooks.get(position).get("position").toString();
        i.putExtra("position", res_id);
        startActivity(intenet);

        هم چنین
        setOnClickListener(this);
        }
        @Override
        public void onClick(View v) {
        Intent intent = new Intent(context,IADetailsActivity.class);
        Bundle extras = new Bundle();
        extras.putInt(“position”,getAdapterPosition());
        intent.putExtras(extras);
        /*
        int i=getAdapterPosition();
        intent.putExtra(“position”, getAdapterPosition());*/
        context.startActivity(intent);

        باتشکر

        پاسخ
  11. SAMYAR

    سلام
    من میخاستم در AIDE یک قسمت جستجوطراحی کنم که متنای داخل اکتییوتی رو نمایش بده ولی نمیشه لطفا کمکم کنید

    پاسخ

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *