পেজিং 2 লাইব্রেরি ওভারভিউ অ্যান্ড্রয়েড জেটপ্যাকের অংশ।
পেজিং লাইব্রেরি আপনাকে এক সময়ে ডেটার ছোট অংশ লোড এবং প্রদর্শন করতে সহায়তা করে। চাহিদা অনুযায়ী আংশিক ডেটা লোড করা নেটওয়ার্ক ব্যান্ডউইথ এবং সিস্টেম সংস্থানগুলির ব্যবহার হ্রাস করে।
এই নির্দেশিকাটি লাইব্রেরির বিভিন্ন ধারণাগত উদাহরণ প্রদান করে, সাথে এটি কীভাবে কাজ করে তার একটি ওভারভিউ সহ। এই লাইব্রেরিটি কীভাবে কাজ করে তার সম্পূর্ণ উদাহরণ দেখতে, অতিরিক্ত সংস্থান বিভাগ থেকে কোডল্যাব এবং নমুনাগুলি চেষ্টা করে দেখুন।
সেটআপ
আপনার অ্যান্ড্রয়েড অ্যাপে পেজিং উপাদান আমদানি করতে, আপনার অ্যাপের build.gradle
ফাইলে নিম্নলিখিত নির্ভরতা যোগ করুন:
Groovy
dependencies { def paging_version = "2.1.2" implementation "androidx.paging:paging-runtime:$paging_version" // For Kotlin use paging-runtime-ktx // alternatively - without Android dependencies for testing testImplementation "androidx.paging:paging-common:$paging_version" // For Kotlin use paging-common-ktx // optional - RxJava support implementation "androidx.paging:paging-rxjava2:$paging_version" // For Kotlin use paging-rxjava2-ktx }
Kotlin
dependencies { val paging_version = "2.1.2" implementation("androidx.paging:paging-runtime:$paging_version") // For Kotlin use paging-runtime-ktx // alternatively - without Android dependencies for testing testImplementation("androidx.paging:paging-common:$paging_version") // For Kotlin use paging-common-ktx // optional - RxJava support implementation("androidx.paging:paging-rxjava2:$paging_version") // For Kotlin use paging-rxjava2-ktx }
লাইব্রেরি আর্কিটেকচার
এই বিভাগটি পেজিং লাইব্রেরির প্রধান উপাদান বর্ণনা করে এবং দেখায়।
পেজডলিস্ট
পেজিং লাইব্রেরির মূল উপাদান হল PagedList
ক্লাস, যা আপনার অ্যাপের ডেটা বা পৃষ্ঠাগুলির অংশগুলি লোড করে। যেহেতু আরও ডেটা প্রয়োজন, এটি বিদ্যমান PagedList
অবজেক্টে পেজ করা হয়েছে। কোনো লোড করা ডেটা পরিবর্তন হলে, একটি LiveData
বা RxJava2-ভিত্তিক অবজেক্ট থেকে পর্যবেক্ষণযোগ্য ডেটা ধারকের কাছে PagedList
এর একটি নতুন উদাহরণ নির্গত হয়। PagedList
অবজেক্ট তৈরি হওয়ার সাথে সাথে, আপনার অ্যাপের UI তাদের বিষয়বস্তু উপস্থাপন করে, আপনার UI কন্ট্রোলারের জীবনচক্রকে সম্মান করার সময়।
নিম্নলিখিত কোড স্নিপেট দেখায় কিভাবে আপনি PagedList
অবজেক্টের LiveData
ধারক ব্যবহার করে ডেটা লোড এবং উপস্থাপন করতে আপনার অ্যাপের ভিউ মডেল কনফিগার করতে পারেন:
কোটলিন
class ConcertViewModel(concertDao: ConcertDao) : ViewModel() { val concertList: LiveData<PagedList<Concert>> = concertDao.concertsByDate().toLiveData(pageSize = 50) }
জাভা
public class ConcertViewModel extends ViewModel { private ConcertDao concertDao; public final LiveData<PagedList<Concert>> concertList; // Creates a PagedList object with 50 items per page. public ConcertViewModel(ConcertDao concertDao) { this.concertDao = concertDao; concertList = new LivePagedListBuilder<>( concertDao.concertsByDate(), 50).build(); } }
ডেটা
PagedList
এর প্রতিটি উদাহরণ তার সংশ্লিষ্ট DataSource
অবজেক্ট থেকে আপনার অ্যাপের ডেটার একটি আপ-টু-ডেট স্ন্যাপশট লোড করে। আপনার অ্যাপের ব্যাকএন্ড বা ডাটাবেস থেকে PagedList
অবজেক্টে ডেটা প্রবাহিত হয়।
নিম্নলিখিত উদাহরণটি আপনার অ্যাপের ডেটা সংগঠিত করতে রুম পারসিসটেন্স লাইব্রেরি ব্যবহার করে, কিন্তু আপনি যদি অন্য কোনও উপায় ব্যবহার করে আপনার ডেটা সঞ্চয় করতে চান তবে আপনি আপনার নিজস্ব ডেটা উত্স কারখানাও প্রদান করতে পারেন৷
কোটলিন
@Dao interface ConcertDao { // The Int type parameter tells Room to use a PositionalDataSource object. @Query("SELECT * FROM concerts ORDER BY date DESC") fun concertsByDate(): DataSource.Factory<Int, Concert> }
জাভা
@Dao public interface ConcertDao { // The Integer type parameter tells Room to use a // PositionalDataSource object. @Query("SELECT * FROM concerts ORDER BY date DESC") DataSource.Factory<Integer, Concert> concertsByDate(); }
আপনি কিভাবে PagedList
অবজেক্টে ডেটা লোড করতে পারেন সে সম্পর্কে আরও জানতে, পৃষ্ঠাযুক্ত ডেটা কীভাবে লোড করবেন তার নির্দেশিকা দেখুন।
UI
PagedList
ক্লাস একটি RecyclerView
এ আইটেম লোড করতে একটি PagedListAdapter
এর সাথে কাজ করে। এই ক্লাসগুলি লোড হওয়ার সাথে সাথে বিষয়বস্তু আনয়ন এবং প্রদর্শন করতে, দৃশ্যের বাইরের বিষয়বস্তু প্রিফেচ করতে এবং বিষয়বস্তুর পরিবর্তনগুলি অ্যানিমেটিং করতে একসাথে কাজ করে৷
আরও জানতে, পৃষ্ঠাযুক্ত তালিকাগুলি কীভাবে প্রদর্শন করবেন তার নির্দেশিকা দেখুন।
বিভিন্ন ডেটা আর্কিটেকচার সমর্থন করে
পেজিং লাইব্রেরি নিম্নলিখিত ডেটা আর্কিটেকচার সমর্থন করে:
- শুধুমাত্র একটি ব্যাকএন্ড সার্ভার থেকে পরিবেশিত.
- শুধুমাত্র একটি অন-ডিভাইস ডাটাবেসে সংরক্ষিত।
- অন্যান্য উত্সগুলির সংমিশ্রণ, একটি ক্যাশে হিসাবে ডিভাইসে ডাটাবেস ব্যবহার করে৷
চিত্র 1 দেখায় কিভাবে এই প্রতিটি আর্কিটেকচার পরিস্থিতিতে ডেটা প্রবাহিত হয়। শুধুমাত্র নেটওয়ার্ক বা ডাটাবেস-শুধু সমাধানের ক্ষেত্রে, ডেটা সরাসরি আপনার অ্যাপের UI মডেলে প্রবাহিত হয়। আপনি যদি একটি সম্মিলিত পদ্ধতি ব্যবহার করেন, তাহলে ডেটা আপনার ব্যাকএন্ড সার্ভার থেকে, একটি অন-ডিভাইস ডাটাবেসে এবং তারপরে আপনার অ্যাপের UI মডেলে প্রবাহিত হয়। প্রতিবার একবারে, প্রতিটি ডেটা প্রবাহের শেষ পয়েন্ট লোড করার জন্য ডেটা শেষ হয়ে যায়, এই সময়ে এটি ডেটা সরবরাহকারী উপাদান থেকে আরও ডেটার অনুরোধ করে। উদাহরণস্বরূপ, যখন একটি অন-ডিভাইস ডাটাবেস ডেটা শেষ হয়ে যায়, তখন এটি সার্ভার থেকে আরও ডেটার অনুরোধ করে।
এই বিভাগের অবশিষ্টাংশ প্রতিটি ডেটা প্রবাহ ব্যবহারের ক্ষেত্রে কনফিগার করার জন্য সুপারিশ প্রদান করে।
শুধুমাত্র নেটওয়ার্ক
একটি ব্যাকএন্ড সার্ভার থেকে ডেটা প্রদর্শন করতে, আপনার নিজস্ব কাস্টম DataSource
অবজেক্টে তথ্য লোড করতে Retrofit API- এর সিঙ্ক্রোনাস সংস্করণ ব্যবহার করুন৷
শুধুমাত্র ডাটাবেস
স্থানীয় স্টোরেজ পর্যবেক্ষণ করতে আপনার RecyclerView
সেট আপ করুন, বিশেষত রুম পারসিসটেন্স লাইব্রেরি ব্যবহার করে। এইভাবে, যখনই আপনার অ্যাপের ডাটাবেসে ডেটা ঢোকানো বা সংশোধন করা হয়, এই পরিবর্তনগুলি স্বয়ংক্রিয়ভাবে RecyclerView
প্রতিফলিত হয় যা এই ডেটা প্রদর্শন করছে।
নেটওয়ার্ক এবং ডাটাবেস
আপনি ডাটাবেস পর্যবেক্ষণ করা শুরু করার পরে, আপনি PagedList.BoundaryCallback
ব্যবহার করে ডাটাবেস কখন ডেটার বাইরে থাকে তা শুনতে পারেন। তারপরে আপনি আপনার নেটওয়ার্ক থেকে আরও আইটেম আনতে পারেন এবং সেগুলিকে ডাটাবেসে সন্নিবেশ করতে পারেন৷ যদি আপনার UI ডাটাবেস পর্যবেক্ষণ করে, তবে আপনাকে যা করতে হবে।
নেটওয়ার্ক ত্রুটিগুলি পরিচালনা করুন
পেজিং লাইব্রেরি ব্যবহার করে আপনি যে ডেটা প্রদর্শন করছেন তা আনয়ন বা পৃষ্ঠা করার জন্য একটি নেটওয়ার্ক ব্যবহার করার সময়, নেটওয়ার্কটিকে সর্বদা "উপলভ্য" বা "অনুপলব্ধ" হিসাবে বিবেচনা না করা গুরুত্বপূর্ণ, কারণ অনেকগুলি সংযোগ বিরতিহীন বা ফ্ল্যাকি:
- একটি নির্দিষ্ট সার্ভার একটি নেটওয়ার্ক অনুরোধে সাড়া দিতে ব্যর্থ হতে পারে।
- ডিভাইসটি এমন একটি নেটওয়ার্কের সাথে সংযুক্ত হতে পারে যা ধীর বা দুর্বল৷
পরিবর্তে, আপনার অ্যাপের ব্যর্থতার জন্য প্রতিটি অনুরোধ পরীক্ষা করা উচিত এবং নেটওয়ার্ক উপলব্ধ না থাকলে যতটা সম্ভব সুন্দরভাবে পুনরুদ্ধার করা উচিত। উদাহরণস্বরূপ, ডেটা রিফ্রেশ পদক্ষেপটি কাজ না করলে ব্যবহারকারীদের নির্বাচন করার জন্য আপনি একটি "পুনরায় চেষ্টা করুন" বোতাম প্রদান করতে পারেন। ডেটা পেজিং ধাপের সময় যদি কোনো ত্রুটি দেখা দেয়, তাহলে পেজিং অনুরোধগুলি স্বয়ংক্রিয়ভাবে পুনরায় চেষ্টা করা ভাল।
আপনার বিদ্যমান অ্যাপ আপডেট করুন
যদি আপনার অ্যাপটি ইতিমধ্যেই একটি ডাটাবেস বা ব্যাকএন্ড উৎস থেকে ডেটা ব্যবহার করে, তাহলে পেজিং লাইব্রেরি প্রদান করে এমন কার্যকারিতায় সরাসরি আপগ্রেড করা সম্ভব। এই বিভাগটি দেখায় কিভাবে একটি অ্যাপ আপগ্রেড করতে হয় যার একটি সাধারণ বিদ্যমান ডিজাইন রয়েছে।
কাস্টম পেজিং সমাধান
আপনি যদি আপনার অ্যাপের ডেটা উৎস থেকে ডেটার ছোট উপসেট লোড করতে কাস্টম কার্যকারিতা ব্যবহার করেন, তাহলে আপনি PagedList
ক্লাস থেকে এই যুক্তিটিকে প্রতিস্থাপন করতে পারেন। PagedList
এর উদাহরণগুলি সাধারণ ডেটা উত্সগুলিতে অন্তর্নির্মিত সংযোগগুলি অফার করে। এই দৃষ্টান্তগুলি RecyclerView
অবজেক্টগুলির জন্য অ্যাডাপ্টারও প্রদান করে যা আপনি আপনার অ্যাপের UI এ অন্তর্ভুক্ত করতে পারেন।
পৃষ্ঠার পরিবর্তে তালিকা ব্যবহার করে ডেটা লোড করা হয়েছে
আপনি যদি আপনার UI এর অ্যাডাপ্টারের জন্য ব্যাকিং ডেটা স্ট্রাকচার হিসাবে একটি ইন-মেমরি তালিকা ব্যবহার করেন, তাহলে তালিকায় আইটেমগুলির সংখ্যা বড় হতে পারে তাহলে একটি PagedList
ক্লাস ব্যবহার করে ডেটা আপডেটগুলি পর্যবেক্ষণ করার কথা বিবেচনা করুন৷ PagedList
এর দৃষ্টান্তগুলি আপনার অ্যাপের UI-তে ডেটা আপডেট পাস করতে LiveData<PagedList>
অথবা Observable<List>
ব্যবহার করতে পারে, লোডের সময় এবং মেমরি ব্যবহার কমিয়ে দেয়। আরও ভাল, আপনার অ্যাপে একটি PagedList
অবজেক্টের সাথে একটি List
বস্তু প্রতিস্থাপন করার জন্য আপনার অ্যাপের UI কাঠামো বা ডেটা আপডেট করার যুক্তিতে কোনো পরিবর্তনের প্রয়োজন নেই।
কার্সার অ্যাডাপ্টার ব্যবহার করে একটি তালিকা দৃশ্যের সাথে একটি ডেটা কার্সার সংযুক্ত করুন৷
আপনার অ্যাপ্লিকেশান একটি ListView
এর সাথে একটি Cursor
থেকে ডেটা সংযুক্ত করতে একটি CursorAdapter
ব্যবহার করতে পারে৷ সেক্ষেত্রে, আপনাকে সাধারণত আপনার অ্যাপের তালিকা UI কন্টেনার হিসাবে একটি ListView
থেকে RecyclerView
এ স্থানান্তর করতে হবে, তারপরে Cursor
কম্পোনেন্টটিকে Room বা PositionalDataSource
দিয়ে প্রতিস্থাপন করতে হবে, Cursor
দৃষ্টান্তগুলি SQLite ডেটাবেস অ্যাক্সেস করছে কিনা তার উপর নির্ভর করে।
কিছু পরিস্থিতিতে, যেমন Spinner
এর উদাহরণগুলির সাথে কাজ করার সময়, আপনি শুধুমাত্র অ্যাডাপ্টারটি প্রদান করেন। একটি লাইব্রেরি তারপর সেই অ্যাডাপ্টারে লোড হওয়া ডেটা নেয় এবং আপনার জন্য ডেটা প্রদর্শন করে। এই পরিস্থিতিতে, আপনার অ্যাডাপ্টারের ডেটার ধরন LiveData<PagedList>
এ পরিবর্তন করুন, তারপর একটি লাইব্রেরি ক্লাস এই আইটেমগুলিকে একটি UI-তে স্ফীত করার চেষ্টা করার আগে একটি ArrayAdapter
অবজেক্টে এই তালিকাটি মুড়ে দিন।
AsyncListUtil ব্যবহার করে অ্যাসিঙ্ক্রোনাসভাবে সামগ্রী লোড করুন
যদি আপনি AsyncListUtil
অবজেক্টগুলিকে অ্যাসিঙ্ক্রোনাসভাবে তথ্যের গ্রুপগুলি লোড এবং প্রদর্শন করতে ব্যবহার করেন, পেজিং লাইব্রেরি আপনাকে আরও সহজে ডেটা লোড করতে দেয়:
- আপনার ডেটা অবস্থানগত হতে হবে না. পেজিং লাইব্রেরি আপনাকে নেটওয়ার্ক সরবরাহ করে এমন কী ব্যবহার করে সরাসরি আপনার ব্যাকএন্ড থেকে ডেটা লোড করতে দেয়।
- আপনার ডেটা অগণিতভাবে বড় হতে পারে। পেজিং লাইব্রেরি ব্যবহার করে, কোনো ডেটা অবশিষ্ট না থাকা পর্যন্ত আপনি পৃষ্ঠাগুলিতে ডেটা লোড করতে পারেন।
- আপনি আরও সহজে আপনার ডেটা পর্যবেক্ষণ করতে পারেন। পেজিং লাইব্রেরি আপনার ডেটা উপস্থাপন করতে পারে যা আপনার অ্যাপের ভিউমডেল একটি পর্যবেক্ষণযোগ্য ডেটা কাঠামোতে ধারণ করে।
ডাটাবেস উদাহরণ
নিম্নলিখিত কোড স্নিপেটগুলি সমস্ত টুকরো একসাথে কাজ করার বিভিন্ন সম্ভাব্য উপায় দেখায়।
LiveData ব্যবহার করে পৃষ্ঠাযুক্ত ডেটা পর্যবেক্ষণ করা
নিম্নলিখিত কোড স্নিপেট দেখায় সমস্ত টুকরা একসাথে কাজ করছে। কনসার্ট ইভেন্টগুলি ডাটাবেসে যুক্ত, সরানো বা পরিবর্তিত হওয়ার সাথে সাথে RecyclerView
এর সামগ্রী স্বয়ংক্রিয়ভাবে এবং দক্ষতার সাথে আপডেট হয়:
কোটলিন
@Dao interface ConcertDao { // The Int type parameter tells Room to use a PositionalDataSource // object, with position-based loading under the hood. @Query("SELECT * FROM concerts ORDER BY date DESC") fun concertsByDate(): DataSource.Factory<Int, Concert> } class ConcertViewModel(concertDao: ConcertDao) : ViewModel() { val concertList: LiveData<PagedList<Concert>> = concertDao.concertsByDate().toLiveData(pageSize = 50) } class ConcertActivity : AppCompatActivity() { public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Use the 'by viewModels()' Kotlin property delegate // from the activity-ktx artifact val viewModel: ConcertViewModel by viewModels() val recyclerView = findViewById(R.id.concert_list) val adapter = ConcertAdapter() viewModel.concertList.observe(this, PagedList(adapter::submitList)) recyclerView.setAdapter(adapter) } } class ConcertAdapter() : PagedListAdapter<Concert, ConcertViewHolder>(DIFF_CALLBACK) { fun onBindViewHolder(holder: ConcertViewHolder, position: Int) { val concert: Concert? = getItem(position) // Note that "concert" is a placeholder if it's null. holder.bindTo(concert) } companion object { private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<Concert>() { // Concert details may have changed if reloaded from the database, // but ID is fixed. override fun areItemsTheSame(oldConcert: Concert, newConcert: Concert) = oldConcert.id == newConcert.id override fun areContentsTheSame(oldConcert: Concert, newConcert: Concert) = oldConcert == newConcert } } }
জাভা
@Dao public interface ConcertDao { // The Integer type parameter tells Room to use a PositionalDataSource // object, with position-based loading under the hood. @Query("SELECT * FROM concerts ORDER BY date DESC") DataSource.Factory<Integer, Concert> concertsByDate(); } public class ConcertViewModel extends ViewModel { private ConcertDao concertDao; public final LiveData<PagedList<Concert>> concertList; public ConcertViewModel(ConcertDao concertDao) { this.concertDao = concertDao; concertList = new LivePagedListBuilder<>( concertDao.concertsByDate(), /* page size */ 50).build(); } } public class ConcertActivity extends AppCompatActivity { @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); ConcertViewModel viewModel = new ViewModelProvider(this).get(ConcertViewModel.class); RecyclerView recyclerView = findViewById(R.id.concert_list); ConcertAdapter adapter = new ConcertAdapter(); viewModel.concertList.observe(this, adapter::submitList); recyclerView.setAdapter(adapter); } } public class ConcertAdapter extends PagedListAdapter<Concert, ConcertViewHolder> { protected ConcertAdapter() { super(DIFF_CALLBACK); } @Override public void onBindViewHolder(@NonNull ConcertViewHolder holder, int position) { Concert concert = getItem(position); if (concert != null) { holder.bindTo(concert); } else { // Null defines a placeholder item - PagedListAdapter automatically // invalidates this row when the actual object is loaded from the // database. holder.clear(); } } private static DiffUtil.ItemCallback<Concert> DIFF_CALLBACK = new DiffUtil.ItemCallback<Concert>() { // Concert details may have changed if reloaded from the database, // but ID is fixed. @Override public boolean areItemsTheSame(Concert oldConcert, Concert newConcert) { return oldConcert.getId() == newConcert.getId(); } @Override public boolean areContentsTheSame(Concert oldConcert, Concert newConcert) { return oldConcert.equals(newConcert); } }; }
RxJava2 ব্যবহার করে পৃষ্ঠাযুক্ত ডেটা পর্যবেক্ষণ করা হচ্ছে
আপনি যদি LiveData
এর পরিবর্তে RxJava2 ব্যবহার করতে পছন্দ করেন, তাহলে আপনি পরিবর্তে একটি Observable
বা Flowable
বস্তু তৈরি করতে পারেন:
কোটলিন
class ConcertViewModel(concertDao: ConcertDao) : ViewModel() { val concertList: Observable<PagedList<Concert>> = concertDao.concertsByDate().toObservable(pageSize = 50) }
জাভা
public class ConcertViewModel extends ViewModel { private ConcertDao concertDao; public final Observable<PagedList<Concert>> concertList; public ConcertViewModel(ConcertDao concertDao) { this.concertDao = concertDao; concertList = new RxPagedListBuilder<>( concertDao.concertsByDate(), /* page size */ 50) .buildObservable(); } }
তারপরে আপনি নিম্নলিখিত স্নিপেটে কোডটি ব্যবহার করে ডেটা পর্যবেক্ষণ শুরু এবং বন্ধ করতে পারেন:
কোটলিন
class ConcertActivity : AppCompatActivity() { private val adapter = ConcertAdapter() // Use the 'by viewModels()' Kotlin property delegate // from the activity-ktx artifact private val viewModel: ConcertViewModel by viewModels() private val disposable = CompositeDisposable() public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val recyclerView = findViewById(R.id.concert_list) recyclerView.setAdapter(adapter) } override fun onStart() { super.onStart() disposable.add(viewModel.concertList .subscribe(adapter::submitList))) } override fun onStop() { super.onStop() disposable.clear() } }
জাভা
public class ConcertActivity extends AppCompatActivity { private ConcertAdapter adapter = new ConcertAdapter(); private ConcertViewModel viewModel; private CompositeDisposable disposable = new CompositeDisposable(); @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); RecyclerView recyclerView = findViewById(R.id.concert_list); viewModel = new ViewModelProvider(this).get(ConcertViewModel.class); recyclerView.setAdapter(adapter); } @Override protected void onStart() { super.onStart(); disposable.add(viewModel.concertList .subscribe(adapter.submitList(flowableList) )); } @Override protected void onStop() { super.onStop(); disposable.clear(); } }
ConcertDao
এবং ConcertAdapter
এর কোড একটি RxJava2- ভিত্তিক সমাধানের জন্য একই রকম যেমন তারা একটি LiveData
ভিত্তিক সমাধানের জন্য।
মতামত প্রদান
এই সম্পদগুলির মাধ্যমে আমাদের সাথে আপনার প্রতিক্রিয়া এবং ধারণা শেয়ার করুন:
- ইস্যু ট্র্যাকার
- সমস্যাগুলি রিপোর্ট করুন যাতে আমরা বাগগুলি ঠিক করতে পারি৷
অতিরিক্ত সম্পদ
পেজিং লাইব্রেরি সম্পর্কে আরও জানতে, নিম্নলিখিত সংস্থানগুলি দেখুন৷
নমুনা
কোডল্যাব
ভিডিও
- অ্যান্ড্রয়েড জেটপ্যাক: রিসাইক্লারভিউ এবং পেজিং (গুগল I/O '18) সহ অসীম তালিকা পরিচালনা করুন
- অ্যান্ড্রয়েড জেটপ্যাক: পেজিং
আপনার জন্য প্রস্তাবিত
- দ্রষ্টব্য: জাভাস্ক্রিপ্ট বন্ধ থাকলে লিঙ্ক টেক্সট প্রদর্শিত হয়
- পেজিং 3 এ স্থানান্তর করুন
- পৃষ্ঠাযুক্ত তালিকা প্রদর্শন করুন
- পৃষ্ঠাযুক্ত ডেটা সংগ্রহ করুন