آموزش پیاده سازی RecyclerView در اندروید


recyclerview در اندروید

RecyclerView در اندروید: نسخه بهینه شده ListView

چند سالی هست که RecyclerView در اندروید جای ListView رو گرفته. البته این ویجت جدید، جایگزین به حقی برای لیست ویو می باشد ، چرا که مزایای بسیار زیادی نسبت به ListView دارد که مهم ترین آن بهینه شدن و استفاده کمتر از منابع سیستم عامل هست.

در این مقاله قصد داریم که پیاده سازی RecyclerView در اندروید را از صفر تا صد انجام بدیم.

پس بهتره که بی هیچ مقدمه ای شیرجه بزنیم تو کد!

 

1- ایجاد پروژه و اضافه کردن ویجت RecyclerView در اندروید استودیو

یک پروژه جدید با یک اکتیویتی خالی میسازیم. اولین کاری که باید انجام بدیم اضافه کردن dependency مربوط به RecyclerView در اندروید گردل هست.

implementation 'androidx.recyclerview:recyclerview:1.0.0'

میریم در فایل xml مون و یک ریسایکلر ویو داخل layout مورد نظرمون ست میکنیم:

<LinearLayout xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android: id="@+id/rv"/>

</LinearLayout>

حالا میریم داخل MainActivity و مانند view هایی که قبلا باهاشون کار کردیم (مثلا TextView و …) RecyclerView خودمون را بعنوان یک فیلد داخل کلاس MainActivity تعریف میکنیم.

سپس در متد onCreate عملیات findViewById رو انجام میدیم. البته به خاطر داشته باشین که وقتی شما بیشتر از یه View دارین ، قطعا قشنگ نیست داخل onCreate و همون وسط بیاید این کارو انجام بدین، خیلی تمیز یک متد بنویسید و تمام findViewById ها رو همون جا بنویسید.

 

2- پیاده سازی RecyclerAdapter

حالا برای استفاده از همین ریسایکلر ویو که تعریف کردید به چیزی نیاز دارید به اسم RecyclerAdapter. پس کلاسی به همین اسم میسازیم.

در واقع این کلاس مسئول نمایش آیتم های مورد نظر ما در ریسایکلر ویو هست. ما به کلاس دیگه ای تو دل همین کلاس نیاز داریم که هر کدوم از ویو های مارو نگه میداره در واقع اینجا جاییه که مثلا من میگم هر آیتم از ریسایلکر ویو شامل چه view هایی میشه. یه جورایی کلیت نقشه رو به ViewHolder میسپریم.

public class RecyclerAdapter {
    class RecyclerViewHolder extends RecyclerView.ViewHolder{
    }
}

در صورتی که کدهای بالا را در اندروید استودیو وارد کنید با error مواجه می شوید.

کافیه روی خط های قرمز بریم و alt+enter را بزنیم تا دلیل به وجود آمدن error ها را متوجه بشیم.

دلیل نمایش error ضرورت وجود متد سازنده (constructor method) برای این کلاسه. یعنی برای این کلاس باید یک constructor تعریف کنیم. چون ریسایکلر ویو هر بار که میخواد آیتم بسازه میره سراغ این کلاس (جلوتر میفهمیم چطور)

class RecyclerViewHolder extends RecyclerView.ViewHolder{

    public RecyclerViewHolder(@NonNull View itemView) {
        super(itemView);
    }
}

خود کلاس RecyclerAdapter از کلاس دیگه ای ارث بری میکنه :

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.RecyclerViewHolder> {

    public class RecyclerViewHolder extends RecyclerView.ViewHolder {
        public RecyclerViewHolder(@NonNull View itemView) {
            super(itemView);
        }
    }
}

دیدین چی شد؟ یادتونه گفتم کلاس ویو هلدری که میسازیم تو دل RecyclerView هست. اما چرا باز هم error داریم؟

چون سه متد ضروری هست که برای ساخت هر ویو از ریسایکلرمون ضروریه.

  • getItemCount
  • onCreateViewHolder
  • onBindViewHolder

حالا قدم به قدم هر کدوم از این متدها رو بررسی میکنیم.

 

3- معرفی متد getItemCount و درست کردن XML برای آیتم های ریسایکلرویو

کار متد getItemCount اینه که تعداد آیتم ها یا سطرهایی که ریسایکلر ویو داره رو مشخص میکنه. ما توی مثال مون فرض میکنیم 20 تا آیتم داریم.

@Override
public int getItemCount() {
    return 20;
}

حالا وقتشه که شکل هر سطر از RecyclerView خودمون رو تعیین کنیم. پس یه فایل xml میسازیم و اسمش رو میذاریم row_item و کدهای زیر را وارد می کنیم.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:paddingBottom="10dp"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="70dp"
        android:layout_height="64dp"
        android:layout_gravity="left"
        android:layout_marginStart="16dp"
        android:layout_marginTop="10dp"
        android:paddingBottom="10dp"
        app:srcCompat="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/textViewTitle"
        android:layout_width="94dp"
        android:layout_height="31dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="231dp"
        android:layout_toRightOf="@+id/imageView"
        android:fontFamily="sans-serif-black"
        android:text="TextView"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/textView"
        android:layout_below="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="30dp"
        android:text="more info about text view"
        android:textSize="19sp" />
</RelativeLayout>

در واقع XML بالا رو برای این ساختیم که بگیم هر سطر از لیست ما چه شکلی باید باشد و چه عناصری داخل خودش جا میده.

مثلا در XML بالا دو تا TextView و یک ImageView درست کردیم.

خروجی کدهای XML بالا ، عکس زیر خواهد بود و هر سطر ما چنین شکل خواهد داشت :

آیتم RecyclerView

4- معرفی متد onCreateViewHolder

در متد onCreateViewHolder به ریسایکلر ویو میگیم که قصد داریم چه جور سطری رو در هر آیتم برای ما نقاشی کنه. در واقع Inflator کارش درست مثل یک نقاشه.

بعد هم به یک ویو آدرس ویو مورد نظرمون رو که باید بسازه رو میدیم (در اینجا row_item هست) ، پارامتر دوم بهش میگیم برای همین جایی که هستیم این کارو انجام بده (parent) و پارامتر سوم در 99% موارد از ما مقدار false رو میخواد.

مورد دیگه ای که اینجا لازم داریم ساختن یک instance از کلاس ViewHolder هست.

کاری که این شی برامون قراره انجام بده رو گفتیم. اینکه view را در دل خودش نگه میداره تا ببینه شامل چه مواردیه و اونارو findViewById کنه.

@NonNull
@Override
public RecyclerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
    View view = layoutInflater.inflate(R.layout.row_item, parent, false);
    RecyclerViewHolder recyclerViewHolder = new RecyclerViewHolder(view);
    return recyclerViewHolder;
}

و همون طور که درباره ویو هولدر حرف زدیم :

class RecyclerViewHolder extends RecyclerView.ViewHolder{

    ImageView imgView;
    TextView titleTxtView;
    TextView textView;
    public RecyclerViewHolder(@NonNull View itemView) {
        super(itemView);
        imgView = itemView.findViewById(R.id.imageView);
        titleTxtView = itemView.findViewById(R.id.textViewTitle);
        textView = itemView.findViewById(R.id.textView);
    }
}

توجه دارید که اینجا itemView در واقع همون View ای هست که در متد onCreateViewHolder ساختیم و به این تابع پاس دادیم. برای همین باید هر کدوم از این textView ها و … رو داخل itemView بگرده و پیدا کنه.

حالا داخل MainActivity میریم و مشخص می کنیم که نحوه نمایش آیتم های ریسایکلر ویو افقی، عمودی، grid و… هست.

recyclerView.setLayoutManager(new LinearLayoutManager(this));

یک راه دیگه برای این کار اینه که در فایل xml که خود ریسایکلر ویو مشخص شده نوع layoutManager رو تعیین کنیم.

 

5- ساخت آداپتر و ارتباط با RecyclerView

قدم بعدی ساخت Adapter و وصل کردن اون ریسایکلر ویو به اون هست:

RecyclerAdapter adapter = new RecyclerAdapter();
recyclerView.setAdapter(adapter);

بیاید یه موردی رو با هم تست کنیم که ریسایکلر ویو چرا اصلا همچین اسمی داره؟!

یه لاگ بندازیم داخل متد onCreateViewHolder و count=0

Log.i(TAG, "onCreateViewHolder: " + count++);

خب قبول دارین که هر بار یک آیتمی ساخته شه این متد صدا زده میشه؟ پس یه نگاهی به لاگ کت بندازیم :

نمونه log های متد oncreateviewholder

یادتونه تعداد آیتم ها رو روی 20تا ست کردیم؟ میبینید فقط پنج بار این متد صدا زده شده و این یعنی هر ویو که از صفحه با اسکرول خارج میشه بازیافت میشه تا ویو از پایین وارد شه و این اتفاق روند کار رو بسیار سریع تر میکنه.

میتونید با عدد getItemCount بازی کنید و ببینید چقدر ریسایکلر رفتار بهینه ای داره.

 

تفاوت لیست ویو و ریسایکلرویو

تصویر بالا تفاوت ListView و RecyclerView در اندروید را به بهترین شکل توضیح می دهد.

در صورتی که قصد دارید اطلاعات بیشتری در مورد این تفاوت ها بدانید ، می توانید مقاله ی مقایسه RecyclerView با ListView را مطالعه فرمایید.

 

6- معرفی متد onBindViewHolder

درسته که در اینجا نمیخواستیم محتوایی داخل ویو هامون تزریق کنیم ، اما در واقعیت یا داریم از یک دیتابیس یا مثلا از یک api ، داده ای رو دریافت میکنیم که باید جایی آنها را به view ها منتقل کنیم.

محلی که این اتفاق میفته دقیقا متدی هست به نام onBindViewHolder . اما برای مثال فرض کنید بخوایم داده ای رو داخل این ویو ها قرار بدیم :

@Override
public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position) {
    holder.textView.setText(String.valueOf(position));
}

تصویر زیر ، خروجی نهایی RecyclerView در اندروید امولاتور می باشد.

خروجی نهایی RecyclerView در اندروید

 

خب کارمون تمومه. خسته نباشید!

این دومین مقاله از سری آموزش های آموزش صفر تا صد اندروید بود.

امیدوارم براتون مفید بوده باشه.

 

به این پست امتیاز دهید

روی ستاره های کلیک کنید و امتیاز بدید

میانگین امتیاز / 5. تعداد:

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

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




Enter Captcha Here : *

Reload Image