ভূমিকা
যেহেতু আপনি ঠিক কী সমস্যায় পড়েছেন তা আপনার প্রশ্ন থেকে সত্যই স্পষ্ট নয়, এই বৈশিষ্ট্যটি কীভাবে বাস্তবায়ন করা যায় সে সম্পর্কে আমি এই দ্রুত পদক্ষেপটি লিখেছিলাম; আপনার যদি এখনও প্রশ্ন থাকে তবে নির্দ্বিধায় জিজ্ঞাসা করুন।
আমি এখানে এই গিটহব রেপোজিটরিতে যা বলছি তার প্রতিটি কাজের উদাহরণ রয়েছে ।
আপনি উদাহরণস্বরূপ প্রকল্প সম্পর্কে আরও জানতে চাইলে প্রকল্পের হোমপেজটি দেখুন ।
যে কোনও ক্ষেত্রে ফলাফলটি দেখতে এরকম কিছু হওয়া উচিত:
আপনি যদি প্রথমে ডেমো অ্যাপ্লিকেশনটির সাথে খেলতে চান তবে আপনি এটি প্লে স্টোর থেকে ইনস্টল করতে পারেন:
যাইহোক শুরু করা যাক।
সেট আপ করা হচ্ছে SearchView
ফোল্ডারে কল করা res/menu
একটি নতুন ফাইল তৈরি করুন main_menu.xml
। এটা এ একটি আইটেম যোগ করতে পারেন এবং সেট actionViewClass
করার android.support.v7.widget.SearchView
। যেহেতু আপনি সমর্থন লাইব্রেরি ব্যবহার করছেন আপনাকে actionViewClass
বৈশিষ্ট্যটি সেট করতে সমর্থন লাইব্রেরির নাম স্থানটি ব্যবহার করতে হবে । আপনার এক্সএমএল ফাইলটি দেখতে এমন কিছু হওয়া উচিত:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_search"
android:title="@string/action_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"/>
</menu>
আপনার Fragment
বা Activity
আপনাকে যথারীতি এই মেনুতে এক্সএমএল স্ফীত করতে হবে, তারপরে আপনি MenuItem
যেটি রয়েছে তার সন্ধান করতে পারেন এবং এতে প্রবেশ করানো পাঠ্যের পরিবর্তনগুলি শুনতে আমরা যা ব্যবহার করতে যাচ্ছি তা SearchView
প্রয়োগ OnQueryTextListener
করতে পারেন SearchView
:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
final MenuItem searchItem = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setOnQueryTextListener(this);
return true;
}
@Override
public boolean onQueryTextChange(String query) {
// Here is where we are going to implement the filter logic
return false;
}
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
এবং এখন SearchView
প্রস্তুত ব্যবহার করতে প্রস্তুত। আমরা onQueryTextChange()
একবার প্রয়োগ বাস্তবায়ন শেষ হলে পরে ফিল্টার যুক্তি প্রয়োগ করব Adapter
।
সেট আপ করা হচ্ছে Adapter
প্রথম এবং সর্বাগ্রে এটি এই মডেল ক্লাসটি আমি এই উদাহরণের জন্য ব্যবহার করতে যাচ্ছি:
public class ExampleModel {
private final long mId;
private final String mText;
public ExampleModel(long id, String text) {
mId = id;
mText = text;
}
public long getId() {
return mId;
}
public String getText() {
return mText;
}
}
এটি কেবলমাত্র আপনার প্রাথমিক মডেল যা একটি পাঠ্য প্রদর্শন করবে RecyclerView
। আমি পাঠ্যটি প্রদর্শন করতে এই লেআউটটি ব্যবহার করতে যাচ্ছি:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="model"
type="com.github.wrdlbrnft.searchablerecyclerviewdemo.ui.models.ExampleModel"/>
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:text="@{model.text}"/>
</FrameLayout>
</layout>
আপনি দেখতে পাচ্ছেন যে আমি ডেটা বাইন্ডিং ব্যবহার করি। যদি আপনি ডেটা বাইন্ডিংয়ের সাথে কখনও কাজ না করেন তবে হতাশ হবেন না! এটি খুব সহজ এবং শক্তিশালী, তবে আমি কীভাবে ব্যাখ্যা করতে পারি না যে এটি কীভাবে এই উত্তরের পরিধিতে কাজ করে।
এই ViewHolder
জন্য ExampleModel
শ্রেণী:
public class ExampleViewHolder extends RecyclerView.ViewHolder {
private final ItemExampleBinding mBinding;
public ExampleViewHolder(ItemExampleBinding binding) {
super(binding.getRoot());
mBinding = binding;
}
public void bind(ExampleModel item) {
mBinding.setModel(item);
}
}
আবার বিশেষ কিছু নয়। আমরা উপরের লেআউট xML এ সংজ্ঞায়িত করেছি বলে এই লেআউটে মডেল শ্রেণিকে আবদ্ধ করতে এটি কেবলমাত্র ডেটা বাইন্ডিং ব্যবহার করে।
এখন আমরা অবশেষে সত্যই আকর্ষণীয় অংশে আসতে পারি: অ্যাডাপ্টার রচনা। আমি এর প্রাথমিক প্রয়োগটি এড়াতে যাচ্ছি Adapter
এবং পরিবর্তে এই উত্তরের জন্য প্রাসঙ্গিক অংশগুলিতে মনোনিবেশ করতে যাচ্ছি।
তবে প্রথমে আমাদের একটি কথা বলতে হবে: SortedList
ক্লাস।
SortedList
SortedList
যার অংশ একটি সম্পূর্ণ আশ্চর্যজনক টুল RecyclerView
গ্রন্থাগার। এটি Adapter
ডেটা সেটে পরিবর্তনগুলি সম্পর্কে অবহিত করার যত্ন নেয় এবং এটি খুব কার্যকর পদ্ধতিতে করে। কেবলমাত্র এটির জন্য আপনাকে প্রয়োজনীয় উপাদানগুলির একটি ক্রম নির্দিষ্ট করে। আপনাকে এমন একটি compare()
পদ্ধতি প্রয়োগের মাধ্যমে তা করা দরকার যা SortedList
কেবল দুটি এর মতো দুটি উপাদানের তুলনা করে Comparator
। তবে List
এটি বাছাইয়ের পরিবর্তে আইটেমগুলিতে বাছাই করার জন্য ব্যবহৃত হয় RecyclerView
!
SortedList
সাথে মিথস্ক্রিয়া Adapter
একটি মাধ্যমে Callback
বর্গ যা আপনি বাস্তবায়ন করতে হবে:
private final SortedList.Callback<ExampleModel> mCallback = new SortedList.Callback<ExampleModel>() {
@Override
public void onInserted(int position, int count) {
mAdapter.notifyItemRangeInserted(position, count);
}
@Override
public void onRemoved(int position, int count) {
mAdapter.notifyItemRangeRemoved(position, count);
}
@Override
public void onMoved(int fromPosition, int toPosition) {
mAdapter.notifyItemMoved(fromPosition, toPosition);
}
@Override
public void onChanged(int position, int count) {
mAdapter.notifyItemRangeChanged(position, count);
}
@Override
public int compare(ExampleModel a, ExampleModel b) {
return mComparator.compare(a, b);
}
@Override
public boolean areContentsTheSame(ExampleModel oldItem, ExampleModel newItem) {
return oldItem.equals(newItem);
}
@Override
public boolean areItemsTheSame(ExampleModel item1, ExampleModel item2) {
return item1.getId() == item2.getId();
}
}
মত কলব্যাক উপরের পদ্ধতিতে onMoved
,onInserted
ইত্যাদি আপনাকে কল করার সমতুল্য অবহিত আপনার পদ্ধতি আছে Adapter
। নীচে তিনটি পদ্ধতি compare
, areContentsTheSame
এবংareItemsTheSame
কি আপনি বস্তুর ধরনের আপনি প্রদর্শন করতে চান এবং অনুযায়ী বাস্তবায়ন নিন বিশ্বে আপনি কততম এই বস্তু পর্দায় প্রদর্শিত হওয়া উচিত না।
এক এক করে এই পদ্ধতিগুলি দিয়ে চলুন:
@Override
public int compare(ExampleModel a, ExampleModel b) {
return mComparator.compare(a, b);
}
এই compare()
পদ্ধতিটি সম্পর্কে আমি আগে কথা বলেছি। এই উদাহরণে আমি কেবল একটিতে কলটি পাস করছিComparator
দুটি এমন মডেলের সাথে তুলনা করে এমন একটিতে । আপনি যদি আইটেমগুলিকে স্ক্রিনের বর্ণানুক্রমিক ক্রমে হাজির করতে চান। এই তুলনাকারী দেখতে এই মত হতে পারে:
private static final Comparator<ExampleModel> ALPHABETICAL_COMPARATOR = new Comparator<ExampleModel>() {
@Override
public int compare(ExampleModel a, ExampleModel b) {
return a.getText().compareTo(b.getText());
}
};
এখন আসুন পরবর্তী পদ্ধতিটি একবার দেখুন:
@Override
public boolean areContentsTheSame(ExampleModel oldItem, ExampleModel newItem) {
return oldItem.equals(newItem);
}
এই পদ্ধতির উদ্দেশ্যটি কোনও মডেলের সামগ্রী পরিবর্তন হয়েছে কিনা তা নির্ধারণ করা। SortedList
ব্যবহারকে এই নির্ধারণ করার জন্য একটি ইভেন্টের পরিবর্তন প্রার্থনা করা প্রয়োজন তাহলে - অন্য কথায় যদি RecyclerView
পুরানো এবং নতুন সংস্করণ ক্রসফেড করা উচিত নয়। আপনার যদি মডেল ক্লাসগুলির একটি সঠিক equals()
এবং hashCode()
বাস্তবায়ন হয় তবে আপনি সাধারণত এটি উপরের মতো প্রয়োগ করতে পারেন। আমরা যদি ক্লাসে একটি equals()
এবং hashCode()
বাস্তবায়ন যুক্ত করি তবে ExampleModel
এটির মতো দেখতে হবে:
public class ExampleModel implements SortedListAdapter.ViewModel {
private final long mId;
private final String mText;
public ExampleModel(long id, String text) {
mId = id;
mText = text;
}
public long getId() {
return mId;
}
public String getText() {
return mText;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ExampleModel model = (ExampleModel) o;
if (mId != model.mId) return false;
return mText != null ? mText.equals(model.mText) : model.mText == null;
}
@Override
public int hashCode() {
int result = (int) (mId ^ (mId >>> 32));
result = 31 * result + (mText != null ? mText.hashCode() : 0);
return result;
}
}
দ্রুত দিক নোট: বেশিরভাগ আইডিই এর মতো অ্যান্ড্রয়েড স্টুডিও, ইন্টেলিজিজ এবং ইক্লিপস তৈরির কার্যকারিতা রয়েছে equals()
এবং hashCode()
একটি বোতামের টিপে আপনার জন্য বাস্তবায়ন! সুতরাং এগুলি আপনাকে নিজে প্রয়োগ করতে হবে না। আপনার আইডিইতে এটি কীভাবে কাজ করে তা ইন্টারনেটে সন্ধান করুন!
এবার আসুন শেষ পদ্ধতিটি একবার দেখুন:
@Override
public boolean areItemsTheSame(ExampleModel item1, ExampleModel item2) {
return item1.getId() == item2.getId();
}
দ্য SortedList
যদি দুটি আইটেম একই জিনিস পড়ুন পরীক্ষা এই পদ্ধতি ব্যবহার করে। সরল কথায় (এটি কীভাবে SortedList
কাজ করে তা ব্যাখ্যা না করে) এটি নির্ধারণ করতে ব্যবহৃত হয় যে কোনও বস্তু ইতিমধ্যে অন্তর্ভুক্ত রয়েছে List
এবং যদি কোনও অ্যাড, মুভ বা পরিবর্তন অ্যানিমেশন চালানো দরকার needs আপনার মডেলগুলির কোনও আইডি থাকলে আপনি সাধারণত এই পদ্ধতিতে কেবল আইডি তুলনা করতে পারেন। এগুলি পরীক্ষা করার জন্য যদি আপনার অন্য কোনও উপায়ে বের করার প্রয়োজন হয় না তবে তবে আপনি এটি প্রয়োগ করে শেষ করেন আপনার নির্দিষ্ট অ্যাপের উপর। সাধারণত সমস্ত মডেলকে একটি আইডি দেওয়ার সহজ বিকল্প - এটি উদাহরণস্বরূপ প্রাথমিক কী ক্ষেত্র হতে পারে যদি আপনি কোনও ডাটাবেস থেকে ডেটা জিজ্ঞাসা করেন।
সঙ্গে SortedList.Callback
সঠিকভাবে বাস্তবায়িত আমরা একটি দৃষ্টান্ত তৈরি করতে পারেন SortedList
:
final SortedList<ExampleModel> list = new SortedList<>(ExampleModel.class, mCallback);
এর কনস্ট্রাক্টরের প্রথম প্যারামিটার হিসাবে SortedList
আপনাকে আপনার মডেলগুলির ক্লাস পাস করতে হবে। অন্যান্য প্যারামিটারটি কেবলমাত্র SortedList.Callback
আমরা উপরে বর্ণিত।
এখন আসুন ব্যবসায় নেমে যাক: আমরা যদি এটির Adapter
সাথে বাস্তবায়ন করি তবে SortedList
এটির মতো দেখতে হবে:
public class ExampleAdapter extends RecyclerView.Adapter<ExampleViewHolder> {
private final SortedList<ExampleModel> mSortedList = new SortedList<>(ExampleModel.class, new SortedList.Callback<ExampleModel>() {
@Override
public int compare(ExampleModel a, ExampleModel b) {
return mComparator.compare(a, b);
}
@Override
public void onInserted(int position, int count) {
notifyItemRangeInserted(position, count);
}
@Override
public void onRemoved(int position, int count) {
notifyItemRangeRemoved(position, count);
}
@Override
public void onMoved(int fromPosition, int toPosition) {
notifyItemMoved(fromPosition, toPosition);
}
@Override
public void onChanged(int position, int count) {
notifyItemRangeChanged(position, count);
}
@Override
public boolean areContentsTheSame(ExampleModel oldItem, ExampleModel newItem) {
return oldItem.equals(newItem);
}
@Override
public boolean areItemsTheSame(ExampleModel item1, ExampleModel item2) {
return item1.getId() == item2.getId();
}
});
private final LayoutInflater mInflater;
private final Comparator<ExampleModel> mComparator;
public ExampleAdapter(Context context, Comparator<ExampleModel> comparator) {
mInflater = LayoutInflater.from(context);
mComparator = comparator;
}
@Override
public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final ItemExampleBinding binding = ItemExampleBinding.inflate(inflater, parent, false);
return new ExampleViewHolder(binding);
}
@Override
public void onBindViewHolder(ExampleViewHolder holder, int position) {
final ExampleModel model = mSortedList.get(position);
holder.bind(model);
}
@Override
public int getItemCount() {
return mSortedList.size();
}
}
দ্য Comparator
বাছাই করতে তাই আমরা একই ব্যবহার করতে পারেন আইটেমটি কন্সট্রাকটর মাধ্যমে পাস হওয়ার সাথে সাথে ব্যবহার Adapter
এমনকি আইটেম একটি ভিন্ন অনুক্রমে প্রদর্শন করা অনুমিত হয় পারেন।
এখন আমরা প্রায় সম্পন্ন! তবে প্রথমে আমাদের আইটেমগুলিতে যুক্ত বা সরানোর একটি উপায় প্রয়োজন Adapter
। এই উদ্দেশ্যে আমরা এমন পদ্ধতিতে যুক্ত করতে পারি Adapter
যা আমাদের আইটেমগুলিতে যুক্ত করতে এবং সরানোর অনুমতি দেয় SortedList
:
public void add(ExampleModel model) {
mSortedList.add(model);
}
public void remove(ExampleModel model) {
mSortedList.remove(model);
}
public void add(List<ExampleModel> models) {
mSortedList.addAll(models);
}
public void remove(List<ExampleModel> models) {
mSortedList.beginBatchedUpdates();
for (ExampleModel model : models) {
mSortedList.remove(model);
}
mSortedList.endBatchedUpdates();
}
আমাদের এখানে কোনও অবহিত পদ্ধতি কল করার দরকার নেই কারণ SortedList
ইতিমধ্যে এটির মাধ্যমে এটি করা হয় SortedList.Callback
! এই পদ্ধতির বাস্তবায়ন এক ব্যতিক্রম সহ বেশ সোজা এগিয়ে রয়েছে: অপসারণ পদ্ধতি যা List
মডেলগুলির একটিকে সরিয়ে দেয় । যেহেতু SortedList
কেবলমাত্র একটি সরানোর পদ্ধতি রয়েছে যা একটি একক অবজেক্টকে সরিয়ে ফেলতে পারে আমাদের তালিকার উপর দিয়ে লুপ করতে হবে এবং একে একে মডেলগুলি অপসারণ করতে হবে। beginBatchedUpdates()
শুরুতে কল করা আমরা SortedList
একসাথে করতে যাচ্ছি সমস্ত পরিবর্তনগুলি ব্যাচ করে এবং পারফরম্যান্সের উন্নতি করে। আমরা যখন ফোন করিendBatchedUpdates()
RecyclerView
একযোগে সকল পরিবর্তন সম্পর্কে অবহিত করা হয়।
অতিরিক্তভাবে আপনাকে যা বুঝতে হবে তা হ'ল আপনি যদি কোনও বস্তু যুক্ত করেন SortedList
এবং এটি ইতিমধ্যে SortedList
এটিতে যুক্ত হয় না be পরিবর্তে এই পদ্ধতিটি SortedList
ব্যবহার করে areContentsTheSame()
অবজেক্টটি পরিবর্তিত হয়েছে কিনা তা নির্ধারণ করতে - এবং এতে যদি আইটেমটি থাকে তবে RecyclerView
আপডেট করা হবে।
যাইহোক, আমি সাধারণত যা পছন্দ করি তা হ'ল একটি পদ্ধতি যা আমাকে RecyclerView
একবারে সমস্ত আইটেম প্রতিস্থাপন করতে দেয় । যা নেই তা থেকে সমস্ত কিছু সরিয়ে ফেলুন List
এবং এতে থাকা সমস্ত আইটেম যুক্ত করুন SortedList
:
public void replaceAll(List<ExampleModel> models) {
mSortedList.beginBatchedUpdates();
for (int i = mSortedList.size() - 1; i >= 0; i--) {
final ExampleModel model = mSortedList.get(i);
if (!models.contains(model)) {
mSortedList.remove(model);
}
}
mSortedList.addAll(models);
mSortedList.endBatchedUpdates();
}
এই পদ্ধতিটি আবার সমস্ত আপডেট একসাথে পারফরম্যান্স বাড়ায় ches প্রথম লুপটি বিপরীত যেহেতু শুরুতে কোনও আইটেম সরিয়ে ফেললে তার পরে আসা সমস্ত আইটেমের সূচিগুলিকে গোলমাল করে দেয় এবং এটি ডেটা অসঙ্গতির মতো সমস্যার কারণ হতে পারে। এরপর আমরা শুধু যোগ List
করতে SortedList
ব্যবহার addAll()
সব আইটেম যা ইতিমধ্যে নয় যোগ করার জন্যSortedList
এবং - ঠিক মত আমি উপরে বর্ণিত - আপডেট সব আইটেম যে ইতিমধ্যেই SortedList
কিন্তু পরিবর্তিত হয়েছে।
এবং এটি দিয়ে Adapter
সম্পূর্ণ হয়। পুরো জিনিসটি দেখতে এমন কিছু হওয়া উচিত:
public class ExampleAdapter extends RecyclerView.Adapter<ExampleViewHolder> {
private final SortedList<ExampleModel> mSortedList = new SortedList<>(ExampleModel.class, new SortedList.Callback<ExampleModel>() {
@Override
public int compare(ExampleModel a, ExampleModel b) {
return mComparator.compare(a, b);
}
@Override
public void onInserted(int position, int count) {
notifyItemRangeInserted(position, count);
}
@Override
public void onRemoved(int position, int count) {
notifyItemRangeRemoved(position, count);
}
@Override
public void onMoved(int fromPosition, int toPosition) {
notifyItemMoved(fromPosition, toPosition);
}
@Override
public void onChanged(int position, int count) {
notifyItemRangeChanged(position, count);
}
@Override
public boolean areContentsTheSame(ExampleModel oldItem, ExampleModel newItem) {
return oldItem.equals(newItem);
}
@Override
public boolean areItemsTheSame(ExampleModel item1, ExampleModel item2) {
return item1 == item2;
}
});
private final Comparator<ExampleModel> mComparator;
private final LayoutInflater mInflater;
public ExampleAdapter(Context context, Comparator<ExampleModel> comparator) {
mInflater = LayoutInflater.from(context);
mComparator = comparator;
}
@Override
public ExampleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final ItemExampleBinding binding = ItemExampleBinding.inflate(mInflater, parent, false);
return new ExampleViewHolder(binding);
}
@Override
public void onBindViewHolder(ExampleViewHolder holder, int position) {
final ExampleModel model = mSortedList.get(position);
holder.bind(model);
}
public void add(ExampleModel model) {
mSortedList.add(model);
}
public void remove(ExampleModel model) {
mSortedList.remove(model);
}
public void add(List<ExampleModel> models) {
mSortedList.addAll(models);
}
public void remove(List<ExampleModel> models) {
mSortedList.beginBatchedUpdates();
for (ExampleModel model : models) {
mSortedList.remove(model);
}
mSortedList.endBatchedUpdates();
}
public void replaceAll(List<ExampleModel> models) {
mSortedList.beginBatchedUpdates();
for (int i = mSortedList.size() - 1; i >= 0; i--) {
final ExampleModel model = mSortedList.get(i);
if (!models.contains(model)) {
mSortedList.remove(model);
}
}
mSortedList.addAll(models);
mSortedList.endBatchedUpdates();
}
@Override
public int getItemCount() {
return mSortedList.size();
}
}
ফিল্টারিং বাস্তবায়ন এখন একমাত্র জিনিস অনুপস্থিত!
ফিল্টার যুক্তি বাস্তবায়ন করা হচ্ছে
ফিল্টার যুক্তি প্রয়োগ করতে আমাদের প্রথমে List
সম্ভাব্য সমস্ত মডেলের একটি নির্ধারণ করতে হবে। এই উদাহরণে আমি একটি তৈরি List
এর ExampleModel
সিনেমা একটি অ্যারে থেকে দৃষ্টান্ত:
private static final String[] MOVIES = new String[]{
...
};
private static final Comparator<ExampleModel> ALPHABETICAL_COMPARATOR = new Comparator<ExampleModel>() {
@Override
public int compare(ExampleModel a, ExampleModel b) {
return a.getText().compareTo(b.getText());
}
};
private ExampleAdapter mAdapter;
private List<ExampleModel> mModels;
private RecyclerView mRecyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
mAdapter = new ExampleAdapter(this, ALPHABETICAL_COMPARATOR);
mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
mBinding.recyclerView.setAdapter(mAdapter);
mModels = new ArrayList<>();
for (String movie : MOVIES) {
mModels.add(new ExampleModel(movie));
}
mAdapter.add(mModels);
}
এখানে বিশেষ কিছু হচ্ছে না, আমরা কেবল তাত্ক্ষণিকভাবে এটি Adapter
সেট করে দিই RecyclerView
। এর পরে আমরা অ্যারেতে List
চলচ্চিত্রের নামগুলি থেকে বেশ কয়েকটি মডেল তৈরি করি MOVIES
। তারপরে আমরা সমস্ত মডেলগুলিতে যুক্ত করি SortedList
।
এখন আমরা ফিরে যেতে পারি onQueryTextChange()
যার আগে আমরা সংজ্ঞা দিয়েছিলাম এবং ফিল্টার যুক্তির প্রয়োগ শুরু করতে পারি:
@Override
public boolean onQueryTextChange(String query) {
final List<ExampleModel> filteredModelList = filter(mModels, query);
mAdapter.replaceAll(filteredModelList);
mBinding.recyclerView.scrollToPosition(0);
return true;
}
এটি আবার বেশ সোজা এগিয়ে। আমরা পদ্ধতি কল filter()
এবং পাস List
এর ExampleModel
পাশাপাশি কোয়েরি স্ট্রিং যেমন সে। আমরা তারপরে ফিরে আসা ফিল্টারগুলিতে কল replaceAll()
করি Adapter
এবং পাস করি । কোনও কিছুর সন্ধান করার সময় ব্যবহারকারী সর্বদা সমস্ত আইটেম দেখতে পারে তা নিশ্চিত করার জন্য আমাদেরও কল করতে হবে। অন্যথায় ফিল্টার করার সময় সম্ভবত স্ক্রলড ডাউন অবস্থায় থাকতে পারে এবং পরে কয়েকটি আইটেম লুকিয়ে রাখতে পারে। শীর্ষে স্ক্রোলিং অনুসন্ধানের সময় আরও ভাল ব্যবহারকারীর অভিজ্ঞতা নিশ্চিত করে।List
filter()
scrollToPosition(0)
RecyclerView
RecyclerView
এখনই কেবল নিজের কাজটি বাস্তবায়ন filter()
করা বাকি রয়েছে:
private static List<ExampleModel> filter(List<ExampleModel> models, String query) {
final String lowerCaseQuery = query.toLowerCase();
final List<ExampleModel> filteredModelList = new ArrayList<>();
for (ExampleModel model : models) {
final String text = model.getText().toLowerCase();
if (text.contains(lowerCaseQuery)) {
filteredModelList.add(model);
}
}
return filteredModelList;
}
প্রথম যে জিনিসটি আমরা এখানে করি তা হল toLowerCase()
ক্যোরি স্ট্রিংয়ের কল । আমরা চাই না যে আমাদের অনুসন্ধান ফাংশনটি কেস সংবেদনশীল হোক এবং toLowerCase()
সমস্ত স্ট্রিংকে কল করে আমরা তুলনামূলকভাবে নিশ্চিত করতে পারি যে কেস নির্বিশেষে আমরা একই ফলাফল প্রত্যাবর্তন করব। এরপরে এটি কেবলমাত্র List
আমরা এটির মধ্যে দিয়েছি এমন সমস্ত মডেলের মাধ্যমে পুনরাবৃত্তি করে এবং অনুসন্ধান করে যে মডেলটির পাঠ্যে ক্যোরি স্ট্রিং রয়েছে কিনা। যদি তা হয় তবে ফিল্টারটিতে মডেলটি যুক্ত করা হয় List
।
এবং এটাই! উপরের কোডটি এপিআই স্তরের 7 এবং তার উপরে চলবে এবং এপিআই স্তর 11 দিয়ে শুরু হবে আপনি আইটেম অ্যানিমেশনগুলি নিখরচায় পাবেন!
আমি বুঝতে পারি যে এটি একটি খুব বিশদ বিবরণ যা সম্ভবত পুরো বিষয়টিটিকে বাস্তবের চেয়ে জটিল মনে হচ্ছে, তবে এমন একটি উপায় রয়েছে যা আমরা এই পুরো সমস্যাটিকে সাধারণীকরণ করতে পারি এবং Adapter
এটি একটি SortedList
আরও সাধারণের উপর ভিত্তি করে বাস্তবায়ন করতে পারি ।
সমস্যাটি সাধারণকরণ এবং অ্যাডাপ্টারকে সরলকরণ
এই বিভাগে আমি খুব বেশি বিশদে যেতে যাচ্ছি না - আংশিক কারণ আমি স্ট্যাক ওভারফ্লোতে উত্তরগুলির জন্য চরিত্রের সীমাটির বিরুদ্ধে চলেছি তবে এর বেশিরভাগই ইতিমধ্যে উপরে বর্ণিত হয়েছে - তবে পরিবর্তনের সংক্ষিপ্তসারটি: আমরা একটি বেস Adapter
ক্লাস বাস্তবায়ন করতে পারি যা ইতিমধ্যে দৃষ্টান্তগুলিতে SortedList
বাধ্যতামূলক মডেলগুলির সাথে কাজ করার বিষয়ে যত্ন নিয়েছে ViewHolder
এবং একটি এর Adapter
উপর ভিত্তি করে বাস্তবায়ন করার জন্য একটি সুবিধাজনক উপায় সরবরাহ করে SortedList
। তার জন্য আমাদের দুটি জিনিস করতে হবে:
- আমাদের একটি তৈরি করা দরকার
ViewModel
ইন্টারফেস হবে যা সমস্ত মডেল ক্লাস প্রয়োগ করতে হবে
- আমাদের একটি
ViewHolder
সাবক্লাস তৈরি করতে হবে যা স্বয়ংক্রিয়ভাবে মডেলগুলিকে আবদ্ধ করতে ব্যবহার করতে পারে এমন একটি bind()
পদ্ধতি নির্ধারণ করে Adapter
।
এটি আমাদের কেবলমাত্র সেই সামগ্রীগুলিতে ফোকাস করতে সহায়তা করে যা RecyclerView
কেবলমাত্র মডেলগুলি প্রয়োগ করে এবং এর সাথে সম্পর্কিত ViewHolder
বাস্তবায়ন করে প্রদর্শিত হবে। এই বেস ক্লাসটি ব্যবহার করে আমাদের এর Adapter
এবং এর জটিলতর বিশদ সম্পর্কে চিন্তা করতে হবে না SortedList
।
SortedListAdapter
স্ট্যাকওভারফ্লোতে উত্তরের চরিত্রের সীমাবদ্ধতার কারণে আমি এই বেস শ্রেণিটি বাস্তবায়নের প্রতিটি পদক্ষেপের মধ্য দিয়ে যেতে পারি না এমনকি এখানে পুরো উত্স কোড যুক্ত করতে পারি না, তবে আপনি এই বেস শ্রেণীর পুরো উত্স কোডটি খুঁজে পেতে পারেন - আমি এটি বলেছি SortedListAdapter
- এটিতে গিটহাব গিস্ট ।
আপনার জীবনকে সহজ করতে আমি jCenter এ একটি লাইব্রেরি প্রকাশ করেছি যা এতে রয়েছে SortedListAdapter
! আপনি যদি এটি ব্যবহার করতে চান তবে আপনাকে যা করতে হবে তা হ'ল আপনার অ্যাপ্লিকেশনটির বিল্ড.gradle ফাইলটিতে এই নির্ভরতা যুক্ত করুন:
compile 'com.github.wrdlbrnft:sorted-list-adapter:0.2.0.1'
আপনি লাইব্রেরির হোমপেজে এই লাইব্রেরি সম্পর্কে আরও তথ্য পেতে পারেন ।
সাজানোলিস্টএডাপ্টার ব্যবহার করে
ব্যবহার SortedListAdapter
করতে আমাদের দুটি পরিবর্তন করতে হবে:
পরিবর্তন করুন ViewHolder
যাতে এটি প্রসারিত হয় SortedListAdapter.ViewHolder
। প্রকারের পরামিতিটি এমন মডেল হওয়া উচিত যা এটির সাথে আবদ্ধ হওয়া উচিত ViewHolder
- এই ক্ষেত্রে ExampleModel
। performBind()
পরিবর্তে আপনাকে আপনার মডেলগুলিতে ডেটা বাঁধতে হবে bind()
।
public class ExampleViewHolder extends SortedListAdapter.ViewHolder<ExampleModel> {
private final ItemExampleBinding mBinding;
public ExampleViewHolder(ItemExampleBinding binding) {
super(binding.getRoot());
mBinding = binding;
}
@Override
protected void performBind(ExampleModel item) {
mBinding.setModel(item);
}
}
আপনার সমস্ত মডেল ViewModel
ইন্টারফেস প্রয়োগ করেছে তা নিশ্চিত করুন :
public class ExampleModel implements SortedListAdapter.ViewModel {
...
}
এর পরে আমাদের আর প্রয়োজন নেই এমন সমস্ত কিছু ExampleAdapter
প্রসারিত করতে SortedListAdapter
এবং মুছে ফেলার জন্য আমাদের কেবল আপডেট আপডেট করতে হবে। প্রকারের পরামিতিটি এমন মডেল হওয়া উচিত যা আপনি কাজ করছেন - এই ক্ষেত্রে ExampleModel
। তবে আপনি যদি বিভিন্ন ধরণের মডেল নিয়ে কাজ করছেন তবে টাইপ প্যারামিটারটি সেট করুন ViewModel
।
public class ExampleAdapter extends SortedListAdapter<ExampleModel> {
public ExampleAdapter(Context context, Comparator<ExampleModel> comparator) {
super(context, ExampleModel.class, comparator);
}
@Override
protected ViewHolder<? extends ExampleModel> onCreateViewHolder(LayoutInflater inflater, ViewGroup parent, int viewType) {
final ItemExampleBinding binding = ItemExampleBinding.inflate(inflater, parent, false);
return new ExampleViewHolder(binding);
}
@Override
protected boolean areItemsTheSame(ExampleModel item1, ExampleModel item2) {
return item1.getId() == item2.getId();
}
@Override
protected boolean areItemContentsTheSame(ExampleModel oldItem, ExampleModel newItem) {
return oldItem.equals(newItem);
}
}
তারপরে আমাদের কাজ শেষ! তবে এক উল্লেখ করতে শেষ জিনিস: SortedListAdapter
একই নেই add()
, remove()
বা replaceAll()
পদ্ধতি আমাদের মূল ExampleAdapter
ছিল। Editor
তালিকার আইটেমগুলিকে সংশোধন করতে এটি পৃথক অবজেক্ট ব্যবহার করে যা edit()
পদ্ধতির মাধ্যমে অ্যাক্সেস করা যায় । সুতরাং আপনি যদি কল করতে হবে এমন আইটেমগুলি সরাতে বা যুক্ত করতে চান edit()
তবে এই Editor
উদাহরণগুলিতে আইটেমগুলি যুক্ত করুন এবং মুছে ফেলুন এবং একবার হয়ে গেলে, commit()
পরিবর্তনগুলিকে প্রয়োগ করার জন্য এটিতে কল করুন SortedList
:
mAdapter.edit()
.remove(modelToRemove)
.add(listOfModelsToAdd)
.commit();
পারফরম্যান্স বাড়ানোর জন্য আপনি যে সমস্ত পরিবর্তনগুলি এইভাবে করেন তা একসাথে মিশানো হয়েছে। replaceAll()
উপরের অধ্যায়গুলিতে আমরা যে পদ্ধতিটি প্রয়োগ করেছি তা এই Editor
বস্তুর উপরেও রয়েছে :
mAdapter.edit()
.replaceAll(mModels)
.commit();
যদি আপনি কল করতে ভুলে যান commit()
তবে আপনার কোনও পরিবর্তনই প্রয়োগ করা হবে না!