কালেকশন উইজেট একই ধরনের অনেক এলিমেন্ট দেখানোর জন্য বিশেষভাবে তৈরি করা হয়, যেমন গ্যালারি অ্যাপ থেকে ছবির কালেকশন, নিউজ অ্যাপ থেকে নিবন্ধ বা কমিউনিকেশন অ্যাপ থেকে মেসেজ। কালেকশন উইজেট সাধারণত দুটি ব্যবহারের ক্ষেত্রে ফোকাস করে: কালেকশন ব্রাউজ করা এবং কালেকশনের কোনও এলিমেন্ট খুলে তার বিস্তারিত ভিউ দেখা। কালেকশন উইজেট উল্লম্বভাবে স্ক্রল করতে পারে।
এইসব উইজেট
RemoteViewsService ব্যবহার করে
রিমোট ডেটা দ্বারা ব্যাক-আপ করা সংগ্রহ দেখায়, যেমন কন্টেন্ট
প্রোভাইডার থেকে। উইজেটটি নিম্নলিখিত ভিউ টাইপের একটি ব্যবহার করে ডেটা উপস্থাপন করে, যা কালেকশন
ভিউ নামে পরিচিত:
ListView: এমন একটি ভিউ যা উল্লম্বভাবে স্ক্রল করা যায় এমন তালিকায় আইটেম দেখায়।
GridView: এমন একটি ভিউ যা টু-ডাইমেনশনাল স্ক্রলিং গ্রিডে আইটেম দেখায়।
StackView: একটি স্ট্যাক করা কার্ড ভিউ—এক ধরনের রোলোডেক্সের মতো—যেখানে
ব্যবহারকারী আগের বা পরের কার্ড দেখতে যথাক্রমে সামনের কার্ডটি উপরে বা নিচে
ফ্লিক করতে পারেন।
AdapterViewFlipper: অ্যাডাপ্টার-ব্যাকড ViewAnimator যা দুই বা তার বেশি ভিউয়ের
মধ্যে অ্যানিমেট করে। একবারে শুধু একটি বাচ্চার তথ্য দেখানো হয়।
এইসব কালেকশন ভিউ রিমোট ডেটা দ্বারা ব্যাক-আপ করা কালেকশন দেখায় বলে, এগুলি তাদের ডেটার সাথে ইউজার ইন্টারফেসকে
বাইন্ড করতে Adapter ব্যবহার করে। Adapter ডেটার সেট থেকে আলাদা আলাদা আইটেমকে
আলাদা আলাদা View অবজেক্টের সাথে বাইন্ড করে।
এবং যেহেতু এই কালেকশন ভিউ অ্যাডাপ্টার দ্বারা ব্যাক-আপ করা হয়, তাই Android ফ্রেমওয়ার্কে
উইজেটে তাদের ব্যবহার সমর্থন করার জন্য অতিরিক্ত আর্কিটেকচার অন্তর্ভুক্ত করতে হবে। উইজেটের প্রসঙ্গে, Adapter-এর পরিবর্তে
RemoteViewsFactory ব্যবহার করা হয়,
যা Adapter ইন্টারফেসের চারপাশে একটি পাতলা র্যাপার। কালেকশনে কোনও নির্দিষ্ট আইটেমের জন্য অনুরোধ করা হলে, RemoteViewsFactory কালেকশনের জন্য আইটেম তৈরি করে এবং RemoteViews অবজেক্ট হিসেবে ফেরত দেয়। আপনার উইজেটে
কালেকশন ভিউ অন্তর্ভুক্ত করতে, RemoteViewsService এবং
RemoteViewsFactory প্রয়োগ করুন।
RemoteViewsService হল এমন একটি পরিষেবা যা রিমোট অ্যাডাপ্টারকে
RemoteViews অবজেক্টের জন্য অনুরোধ করতে দেয়। RemoteViewsFactory হল একটি অ্যাডাপ্টারের ইন্টারফেস
যা কালেকশন ভিউ—যেমন ListView, GridView এবং
StackView—এবং সেই ভিউয়ের অন্তর্নিহিত ডেটার মধ্যে কাজ করে। StackWidget
স্যাম্পেল থেকে,
এই পরিষেবা ও ইন্টারফেস প্রয়োগ করার জন্য বয়লারপ্লেট কোডের উদাহরণ এখানে দেওয়া হল:
class StackWidgetService : RemoteViewsService() { override fun onGetViewFactory(intent: Intent): RemoteViewsFactory = StackRemoteViewsFactory(this.applicationContext, intent) } class StackRemoteViewsFactory( private val context: Context, intent: Intent ) : RemoteViewsService.RemoteViewsFactory { // See the RemoteViewsFactory API reference for the full list of methods to implement. }
স্যাম্পেল অ্যাপ্লিকেশন
এই বিভাগে কোডের উদ্ধৃতিগুলিও StackWidget
স্যাম্পেল থেকে নেওয়া হয়েছে:
StackWidget.এই স্যাম্পেলে দশটি ভিউয়ের স্ট্যাক আছে যা শূন্য থেকে নয় পর্যন্ত ভ্যালু দেখায়। স্যাম্পেল উইজেটের এই প্রাথমিক আচরণ আছে:
ব্যবহারকারী উইজেটের টপ ভিউ উল্লম্বভাবে ফ্লিং করে পরবর্তী বা পূর্ববর্তী ভিউ দেখতে পারেন। এটি একটি বিল্ট-ইন
StackViewআচরণ।ব্যবহারকারীর কোনও ইন্টার্যাকশন ছাড়াই, উইজেট অটোমেটিক স্লাইডশোর মতো ক্রম অনুসারে এর ভিউতে এগিয়ে যায়।
res/xml/stackwidgetinfo.xmlফাইলেরandroid:autoAdvanceViewId="@id/stack_view"সেটিংয়ের কারণে এটি হয়েছে। এই সেটিং ভিউ আইডিতে প্রযোজ্য হয়, যা এই ক্ষেত্রে স্ট্যাক ভিউয়ের ভিউ আইডি।ব্যবহারকারী টপ ভিউতে টাচ করলে, উইজেট
Toastমেসেজ "টাচ করা ভিউ n" দেখায়, যেখানে n হল টাচ করা ভিউয়ের ইন্ডেক্স (পজিশন)। কীভাবে আচরণ প্রয়োগ করতে হয় সেই বিষয়ে আরও আলোচনার জন্য, আচরণকে স্বতন্ত্র আইটেমে যোগ করুন বিভাগ দেখুন।
কালেকশন সহ উইজেট প্রয়োগ করুন
কালেকশন সহ উইজেট প্রয়োগ করতে, যেকোনও উইজেট প্রয়োগ করার পদ্ধতি অনুসরণ করুন, তারপরে আরও কয়েকটি ধাপ অনুসরণ করুন:
ম্যানিফেস্ট পরিবর্তন করুন, উইজেট লেআউটে কালেকশন ভিউ যোগ করুন এবং আপনার AppWidgetProvider সাবক্লাস পরিবর্তন করুন।
কালেকশন সহ উইজেটের জন্য ম্যানিফেস্ট
ম্যানিফেস্টে উইজেট ঘোষণা করুন বিভাগে তালিকাভুক্ত প্রয়োজনীয়তা ছাড়াও, আপনাকে এমন ব্যবস্থা করতে হবে যাতে কালেকশন সহ উইজেট আপনার RemoteViewsService-এর সাথে
বাইন্ড করা যায়। এটি করতে, আপনার ম্যানিফেস্ট ফাইলে
BIND_REMOTEVIEWS
অনুমতি সহ পরিষেবাটি ঘোষণা করুন।
এটি অন্যান্য অ্যাপ্লিকেশনকে আপনার উইজেটের ডেটা অবাধে অ্যাক্সেস করা থেকে আটকায়।
যেমন, RemoteViewsService ব্যবহার করে কালেকশন ভিউ পপুলেট করার জন্য কোনও উইজেট তৈরি করার সময়, ম্যানিফেস্ট এন্ট্রি এইরকম দেখতে হতে পারে:
<service android:name="MyWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS" />
এই উদাহরণে, android:name="MyWidgetService" হল RemoteViewsService-এর সাবক্লাস।
কালেকশন সহ উইজেটের লেআউট
আপনার উইজেট লেআউট XML ফাইলের প্রধান প্রয়োজনীয়তা হল, এতে নিম্নলিখিত কালেকশন ভিউয়ের মধ্যে
একটি অন্তর্ভুক্ত থাকতে হবে: ListView, GridView, StackView, অথবা
AdapterViewFlipper. StackWidget
স্যাম্পেলের জন্য
widget_layout.xml ফাইল এখানে দেওয়া হল:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <StackView android:id="@+id/stack_view" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:loopViews="true" /> <TextView android:id="@+id/empty_view" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:background="@drawable/widget_item_background" android:textColor="#ffffff" android:textStyle="bold" android:text="@string/empty_view_text" android:textSize="20sp" /> </FrameLayout>
মনে রাখবেন যে খালি ভিউ অবশ্যই কালেকশন ভিউয়ের সিবলিং হতে হবে যার জন্য খালি ভিউ খালি অবস্থা দেখায়।
আপনার সম্পূর্ণ উইজেটের লেআউট ফাইল ছাড়াও, আরেকটি লেআউট ফাইল তৈরি করুন
যা কালেকশনের প্রতিটি আইটেমের লেআউট নির্ধারণ করে—যেমন,
বইয়ের কালেকশনে প্রতিটি বইয়ের জন্য লেআউট। StackWidget স্যাম্পেলে
শুধুমাত্র একটি আইটেম লেআউট ফাইল, widget_item.xml আছে, কারণ সব আইটেম একই
লেআউট ব্যবহার করে।
কালেকশন সহ উইজেটের জন্য AppWidgetProvider ক্লাস
সাধারণ উইজেটের মতো, আপনার
AppWidgetProvider সাবক্লাসের
বেশিরভাগ কোড
সাধারণত
onUpdate()-এ যায়।
কালেকশন সহ উইজেট তৈরি করার সময় onUpdate()-এর জন্য আপনার ইমপ্লিমেন্টেশনে প্রধান পার্থক্য হল যে আপনাকে অবশ্যই
setRemoteAdapter() কল করতে হবে।
এটি কালেকশন ভিউকে বলে যে তার ডেটা কোথা থেকে পেতে হবে।
RemoteViewsService তারপর আপনার
RemoteViewsFactory-এর ইমপ্লিমেন্টেশন ফিরিয়ে দিতে পারে এবং উইজেট উপযুক্ত ডেটা দেখাতে পারে। আপনি এই পদ্ধতি কল করলে,
এমন একটি ইনটেন্ট পাস করুন যা আপনার RemoteViewsService-এর ইমপ্লিমেন্টেশন এবং
উইজেট আইডিকে পয়েন্ট করে, যা আপডেট করার জন্য উইজেটকে নির্দিষ্ট করে।
যেমন, StackWidget স্যাম্পেল কীভাবে onUpdate() কলব্যাক পদ্ধতি প্রয়োগ করে
RemoteViewsService-কে উইজেট কালেকশনের জন্য রিমোট অ্যাডাপ্টার হিসেবে সেট করে তা এখানে দেওয়া হল:
override fun onUpdate( context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray ) { // Update each of the widgets with the remote adapter. appWidgetIds.forEach { appWidgetId -> // Set up the intent that starts the StackViewService, which // provides the views for this collection. val intent = Intent(context, StackWidgetService::class.java).apply { // Add the widget ID to the intent extras. putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME)) } // Instantiate the RemoteViews object for the widget layout. val views = RemoteViews(context.packageName, R.layout.widget_layout).apply { // Set up the RemoteViews object to use a RemoteViews adapter. // This adapter connects to a RemoteViewsService through the // specified intent. // This is how you populate the data. setRemoteAdapter(R.id.stack_view, intent) // The empty view is displayed when the collection has no items. // It must be in the same layout used to instantiate the // RemoteViews object. setEmptyView(R.id.stack_view, R.id.empty_view) } // Do additional processing specific to this widget. appWidgetManager.updateAppWidget(appWidgetId, views) } super.onUpdate(context, appWidgetManager, appWidgetIds) }
ডেটা ধরে রাখা
এই পৃষ্ঠায় যেমন বর্ণনা করা হয়েছে, RemoteViewsService সাবক্লাস
RemoteViewsFactory প্রদান করে যা রিমোট কালেকশন ভিউ পপুলেট করতে ব্যবহার করা হয়।
বিশেষ করে, এইসব ধাপ অনুসরণ করুন:
সাবক্লাস
RemoteViewsService।RemoteViewsServiceহল এমন একটি পরিষেবা যার মাধ্যমে রিমোট অ্যাডাপ্টারRemoteViews-এর জন্য অনুরোধ করতে পারে।আপনার
RemoteViewsServiceসাবক্লাসে, এমন একটি ক্লাস অন্তর্ভুক্ত করুন যাRemoteViewsFactoryইন্টারফেস প্রয়োগ করে।RemoteViewsFactoryহল রিমোট কালেকশন ভিউ—যেমনListView,GridView,StackView—এবং সেই ভিউয়ের অন্তর্নিহিত ডেটার মধ্যে অ্যাডাপ্টারের জন্য একটি ইন্টারফেস। আপনার ইমপ্লিমেন্টেশন ডেটাসেটের প্রতিটি আইটেমের জন্য একটিRemoteViewsঅবজেক্ট তৈরি করার জন্য দায়ী। এই ইন্টারফেসটিAdapter-এর চারপাশে একটি পাতলা র্যাপার।
আপনার পরিষেবার কোনও একটি ইনস্ট্যান্স বা এতে থাকা কোনও ডেটা স্থায়ীভাবে থাকবে বলে
আপনি ধরে নিতে পারবেন না। আপনার RemoteViewsService-এ ডেটা স্ট্যাটিক না হলে তা স্টোর করবেন না। আপনি
যদি চান যে আপনার উইজেটের ডেটা থেকে যাক, তাহলে সবচেয়ে ভালো উপায় হল এমন একটি
ContentProvider ব্যবহার করা যার ডেটা
প্রসেস লাইফসাইকেলের পরেও থেকে যায়। যেমন, কোনও মুদিখানার দোকানের উইজেট
প্রতিটি মুদিখানার লিস্টের আইটেমের স্ট্যাটাস একটি স্থায়ী লোকেশনে স্টোর করতে পারে, যেমন
SQL ডেটাবেস।
RemoteViewsService প্রয়োগের প্রাথমিক কন্টেন্ট হল এর
RemoteViewsFactory, যা নিম্নলিখিত বিভাগে বর্ণনা করা হয়েছে।
RemoteViewsFactory ইন্টারফেস
আপনার কাস্টম ক্লাস যা RemoteViewsFactory ইন্টারফেস প্রয়োগ করে তা
উইজেটকে তার সংগ্রহের আইটেমগুলির ডেটা প্রদান করে। এটি করার জন্য, এটি
আপনার উইজেট আইটেম XML লেআউট ফাইলকে ডেটার সোর্সের সাথে একত্রিত করে। ডেটার এই সোর্স
ডেটাবেস থেকে শুরু করে অ্যারে পর্যন্ত যেকোনও কিছু হতে পারে। StackWidget
স্যাম্পেলে, ডেটা সোর্স হল WidgetItems-এর অ্যারে। RemoteViewsFactory
রিমোট কালেকশন ভিউতে ডেটা যোগ করার জন্য অ্যাডাপ্টার হিসেবে কাজ করে।
আপনার RemoteViewsFactory সাবক্লাসের জন্য আপনাকে দুটি সবচেয়ে গুরুত্বপূর্ণ পদ্ধতি প্রয়োগ করতে হবে, সেগুলি হল onCreate() এবং getViewAt()।
প্রথমবার আপনার ফ্যাক্টরি তৈরি করার সময় সিস্টেম onCreate() কল করে।
এখানে আপনি নিজের ডেটা সোর্সের সাথে যেকোনও কানেকশন বা কার্সর সেট-আপ করেন। যেমন, StackWidget স্যাম্পেল WidgetItem অবজেক্টের অ্যারে শুরু করতে onCreate() ব্যবহার
করে। আপনার উইজেট অ্যাক্টিভ থাকলে, সিস্টেম অ্যারেতে তাদের ইনডেক্স পজিশন ব্যবহার করে এইসব
অবজেক্ট অ্যাক্সেস করে এবং সেগুলিতে থাকা টেক্সট
দেখায়।
এখানে StackWidget স্যাম্পেলের RemoteViewsFactory
ইমপ্লিমেন্টেশন থেকে একটি উদ্ধৃতি দেওয়া হল যা onCreate() পদ্ধতির অংশগুলি দেখায়:
private const val REMOTE_VIEW_COUNT: Int = 10 class StackRemoteViewsFactory( private val context: Context ) : RemoteViewsService.RemoteViewsFactory { private lateinit var widgetItems: List<WidgetItem> override fun onCreate() { // In onCreate(), set up any connections or cursors to your data // source. Heavy lifting, such as downloading or creating content, // must be deferred to onDataSetChanged() or getViewAt(). Taking // more than 20 seconds on this call results in an ANR. widgetItems = List(REMOTE_VIEW_COUNT) { index -> WidgetItem("$index!") } } }
RemoteViewsFactory পদ্ধতি getViewAt() ডেটাসেটে নির্দিষ্ট position-এ ডেটার সাথে সম্পর্কিত
RemoteViews অবজেক্ট প্রদান করে। এখানে
StackWidget স্যাম্পেলের RemoteViewsFactory ইমপ্লিমেন্টেশন থেকে একটি উদ্ধৃতি দেওয়া হল:
override fun getViewAt(position: Int): RemoteViews { // Construct a remote views item based on the widget item XML file // and set the text based on the position. return RemoteViews(context.packageName, R.layout.widget_item).apply { setTextViewText(R.id.widget_item, widgetItems[position].text) } }
আলাদা আলাদা আইটেমে আচরণ যোগ করুন
আগের বিভাগগুলি দেখায় যে কীভাবে আপনার ডেটা আপনার উইজেট সংগ্রহে বাইন্ড করতে হয়। কিন্তু আপনার কালেকশন ভিউতে স্বতন্ত্র আইটেমে ডায়নামিক আচরণ যোগ করতে চাইলে কী করবেন?
onUpdate()
ক্লাসের মাধ্যমে ইভেন্ট ম্যানেজ করা-তে যেমন বর্ণনা করা হয়েছে, আপনি সাধারণত
setOnClickPendingIntent() ব্যবহার করে কোনও অবজেক্টের ক্লিক সংক্রান্ত আচরণ সেট করেন—যেমন
কোনও বোতামে ক্লিক করলে Activity লঞ্চ করা। তবে,
কোনও স্বতন্ত্র সংগ্রহ আইটেমে চাইল্ড ভিউয়ের জন্য এই পদ্ধতি অনুমোদিত নয়।
যেমন, আপনি Gmail উইজেটে গ্লোবাল বোতাম সেট-আপ করতে setOnClickPendingIntent() ব্যবহার করতে পারেন
যা অ্যাপ চালু করে, কিন্তু স্বতন্ত্র তালিকা আইটেমে
নয়।
পরিবর্তে, কোনও কালেকশনের স্বতন্ত্র আইটেমে ক্লিক বিহেভিয়ার যোগ করতে, setOnClickFillInIntent() ব্যবহার করুন। আপনার কালেকশন ভিউয়ের জন্য পেন্ডিং ইনটেন্ট টেমপ্লেট সেট-আপ করুন এবং
আপনার RemoteViewsFactory ব্যবহার করে কালেকশনের প্রতিটি আইটেমে
একটি ফিল-ইন ইনটেন্ট সেট করুন।
এই বিভাগে StackWidget স্যাম্পেল ব্যবহার করে দেখানো হয়েছে যে কীভাবে আলাদা আলাদা আইটেমে
আচরণ যোগ করতে হয়। StackWidget স্যাম্পেলে, ব্যবহারকারী টপ ভিউ স্পর্শ করলে,
উইজেট Toast মেসেজ "স্পর্শ করা ভিউ n" দেখায়, যেখানে n হল
স্পর্শ করা ভিউয়ের ইন্ডেক্স (পজিশন)। এটি কীভাবে কাজ করে তা এখানে দেওয়া হল:
StackWidgetProvider—একটিAppWidgetProviderসাবক্লাস—TOAST_ACTIONনামক কাস্টম অ্যাকশন সহ একটি পেন্ডিং ইনটেন্ট তৈরি করে।ব্যবহারকারী কোনও ভিউ টাচ করলে, ইনটেন্ট ফায়ার করে এবং এটি
TOAST_ACTIONব্রডকাস্ট করে।এই ব্রডকাস্ট
StackWidgetProviderক্লাসেরonReceive()পদ্ধতি দ্বারা ইন্টারসেপ্ট করা হয় এবং টাচ করা ভিউয়ের জন্য উইজেটToastমেসেজ দেখায়। সংগ্রহের আইটেমের ডেটাRemoteViewsFactory-এর মাধ্যমেRemoteViewsServiceপ্রদান করে।
বাকি থাকা ইনটেন্ট টেমপ্লেট সেট-আপ করুন
StackWidgetProvider (একটি AppWidgetProvider সাবক্লাস)
পেন্ডিং ইনটেন্ট সেট-আপ করে। কালেকশনের স্বতন্ত্র আইটেমগুলি তাদের নিজস্ব পেন্ডিং ইনটেন্ট
সেট-আপ করতে পারে না। পরিবর্তে, কালেকশনটি সামগ্রিকভাবে একটি পেন্ডিং ইনটেন্ট টেমপ্লেট সেট-আপ করে এবং প্রতিটি আইটেম একটি ফিল-ইন ইনটেন্ট সেট করে যাতে আইটেম-বাই-আইটেম ভিত্তিতে অনন্য আচরণ তৈরি করা যায়।
ব্যবহারকারী কোনও ভিউ টাচ করলে যে ব্রডকাস্ট পাঠানো হয়, এই ক্লাস সেটিও রিসিভ করে। এটি onReceive() পদ্ধতিতে এই ইভেন্ট প্রসেস করে। ইনটেন্টের অ্যাকশন TOAST_ACTION হলে, বর্তমান ভিউয়ের জন্য উইজেট Toast মেসেজ দেখায়।
const val TOAST_ACTION = "com.example.android.stackwidget.TOAST_ACTION" const val EXTRA_ITEM = "com.example.android.stackwidget.EXTRA_ITEM" class StackWidgetProvider : AppWidgetProvider() { // ... // Called when the BroadcastReceiver receives an Intent broadcast. // Checks whether the intent's action is TOAST_ACTION. If it is, the // widget displays a Toast message for the current item. override fun onReceive(context: Context, intent: Intent) { val mgr: AppWidgetManager = AppWidgetManager.getInstance(context) if (intent.action == TOAST_ACTION) { val appWidgetId: Int = intent.getIntExtra( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID ) // EXTRA_ITEM represents a custom value provided by the Intent // passed to the setOnClickFillInIntent() method to indicate the // position of the clicked item. See StackRemoteViewsFactory in // Set the fill-in Intent for details. val viewIndex: Int = intent.getIntExtra(EXTRA_ITEM, 0) Toast.makeText(context, "Touched view $viewIndex", Toast.LENGTH_SHORT).show() } super.onReceive(context, intent) } override fun onUpdate( context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray ) { // Update each of the widgets with the remote adapter. appWidgetIds.forEach { appWidgetId -> // Sets up the intent that points to the StackViewService that // provides the views for this collection. val intent = Intent(context, StackWidgetService::class.java).apply { putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) // When intents are compared, the extras are ignored, so embed // the extra sinto the data so that the extras are not ignored. data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME)) } val rv = RemoteViews(context.packageName, R.layout.widget_layout).apply { setRemoteAdapter(R.id.stack_view, intent) // The empty view is displayed when the collection has no items. // It must be a sibling of the collection view. setEmptyView(R.id.stack_view, R.id.empty_view) } // This section makes it possible for items to have individualized // behavior. It does this by setting up a pending intent template. // Individuals items of a collection can't set up their own pending // intents. Instead, the collection as a whole sets up a pending // intent template, and the individual items set a fillInIntent // to create unique behavior on an item-by-item basis. val toastPendingIntent: PendingIntent = Intent( context, StackWidgetProvider::class.java ).run { // Set the action for the intent. // When the user touches a particular view, it has the effect of // broadcasting TOAST_ACTION. action = TOAST_ACTION putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) data = Uri.parse(toUri(Intent.URI_INTENT_SCHEME)) // The template must be mutable, because each item fills in its // own extras through setOnClickFillInIntent(). PendingIntent.getBroadcast( context, 0, this, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE ) } rv.setPendingIntentTemplate(R.id.stack_view, toastPendingIntent) appWidgetManager.updateAppWidget(appWidgetId, rv) } super.onUpdate(context, appWidgetManager, appWidgetIds) } }
ফিল-ইন ইনটেন্ট সেট করুন
আপনার RemoteViewsFactory-কে অবশ্যই সংগ্রহের প্রতিটি আইটেমে একটি ফিল-ইন ইনটেন্ট সেট করতে হবে। এর ফলে, প্রদত্ত আইটেমের আলাদা আলাদা অন-ক্লিক অ্যাকশন
শনাক্ত করা সম্ভব হয়। আইটেমে ট্যাপ করা হলে যে চূড়ান্ত ইনটেন্ট কার্যকর করা হয় তা নির্ধারণ করতে
PendingIntent টেমপ্লেটের সাথে
ফিল-ইন ইনটেন্ট যোগ করা হয়।
private const val REMOTE_VIEW_COUNT: Int = 10 class StackRemoteViewsFactory( private val context: Context, intent: Intent ) : RemoteViewsService.RemoteViewsFactory { private lateinit var widgetItems: List<WidgetItem> private val appWidgetId: Int = intent.getIntExtra( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID ) override fun onCreate() { // In onCreate(), set up any connections or cursors to your data source. // Heavy lifting, such as downloading or creating content, must be // deferred to onDataSetChanged() or getViewAt(). Taking more than 20 // seconds on this call results in an ANR. widgetItems = List(REMOTE_VIEW_COUNT) { index -> WidgetItem("$index!") } // ... } // ... override fun getViewAt(position: Int): RemoteViews { // Construct a remote views item based on the widget item XML file // and set the text based on the position. return RemoteViews(context.packageName, R.layout.widget_item).apply { setTextViewText(R.id.widget_item, widgetItems[position].text) // Set a fill-intent to fill in the pending intent template. // that is set on the collection view in StackWidgetProvider. val fillInIntent = Intent().apply { Bundle().also { extras -> extras.putInt(EXTRA_ITEM, position) putExtras(extras) } } // Make it possible to distinguish the individual on-click // action of a given item. setOnClickFillInIntent(R.id.widget_item, fillInIntent) // ... } } // ... }
সংগ্রহের ডেটা আপ-টু-ডেট রাখুন
ছবি ২-এ কালেকশন ব্যবহার করে এমন উইজেটে আপডেট ফ্লো দেখানো হয়েছে। এটি দেখায়
কীভাবে উইজেট কোড RemoteViewsFactory-এর সাথে ইন্টার্যাক্ট করে এবং কীভাবে আপনি
আপডেট ট্রিগার করতে পারেন:
RemoteViewsFactory-এর সাথে ইন্টার্যাকশন।যেসব উইজেট সংগ্রহ ব্যবহার করে সেগুলি ব্যবহারকারীদের আপ-টু-ডেট কন্টেন্ট প্রদান করতে পারে। যেমন, Gmail উইজেট ব্যবহারকারীদের তাদের ইনবক্সের একটি স্ন্যাপশট দেয়। এটি সম্ভব করতে, নতুন ডেটা ফেচ ও ডিসপ্লে করতে আপনার RemoteViewsFactory ও কালেকশন ভিউ ট্রিগার করুন।
এটি করতে, notifyAppWidgetViewDataChanged()-এ কল করার জন্য
AppWidgetManager ব্যবহার করুন। এই কলের ফলে আপনার RemoteViewsFactory অবজেক্টের onDataSetChanged()
মেথডে কলব্যাক করা হয়, যার ফলে আপনি যেকোনও নতুন ডেটা ফেচ করতে পারেন।
আপনি onDataSetChanged() কলব্যাকের মধ্যে প্রসেসিং-ইনটেনসিভ অপারেশন সিঙ্ক্রোনাসভাবে
সম্পাদন করতে পারেন। RemoteViewsFactory থেকে মেটাডেটা বা ভিউ ডেটা ফেচ করার আগেই
এই কল সম্পূর্ণ হয়ে যায়। এছাড়াও, আপনি
getViewAt()
পদ্ধতির মধ্যে প্রসেসিং-ইনটেনসিভ অপারেশন পারফর্ম করতে পারবেন। এই কলটি সম্পূর্ণ হতে বেশি সময় লাগলে, লোডিং ভিউ—যা
RemoteViewsFactory অবজেক্টের
getLoadingView()
মেথড দ্বারা নির্দিষ্ট করা হয়—তা কালেকশন ভিউয়ের সংশ্লিষ্ট পজিশনে
এটি সম্পূর্ণ না হওয়া পর্যন্ত দেখানো হয়।
সরাসরি কোনও কালেকশন পাস করতে RemoteCollectionItems ব্যবহার করুন
Android 12 (API লেভেল 31) setRemoteAdapter(int viewId,
RemoteViews.RemoteCollectionItems
items)
পদ্ধতি যোগ করে, যা আপনার অ্যাপকে সরাসরি একটি কালেকশন পাস করতে দেয় যখন একটি
কালেকশন ভিউ পপুলেট করা হয়। আপনি এই পদ্ধতি ব্যবহার করে অ্যাডাপ্টার সেট করলে, আপনাকে
RemoteViewsFactory প্রয়োগ করতে হবে না এবং আপনাকে
notifyAppWidgetViewDataChanged() কল করতে হবে না।
আপনার অ্যাডাপ্টার পপুলেট করা সহজ করার পাশাপাশি, এই পদ্ধতিটি
ব্যবহারকারীরা নতুন আইটেম দেখার জন্য তালিকার মাধ্যমে স্ক্রল করার সময় নতুন আইটেম পপুলেট করার জন্য লেটেন্সিও
সরিয়ে দেয়। আপনার কালেকশন আইটেমের সেট তুলনামূলকভাবে ছোট হলে,
অ্যাডাপ্টার সেট করার এই পদ্ধতিটিই বেশি পছন্দ করা হয়। তবে, উদাহরণস্বরূপ, আপনার সংগ্রহে setImageViewBitmap-এ পাস করা অসংখ্য Bitmaps থাকলে এই পদ্ধতিটি ভাল কাজ করে না।
কালেকশন যদি লেআউটের কনস্ট্যান্ট সেট ব্যবহার না করে—অর্থাৎ, কিছু আইটেম যদি
কখনও কখনও উপস্থিত থাকে—তাহলে কালেকশনে থাকতে পারে এমন অনন্য লেআউটের সর্বাধিক সংখ্যা নির্দিষ্ট করতে
setViewTypeCount ব্যবহার করুন। এর ফলে আপনার অ্যাপ উইজেট আপডেট করার সময়
অ্যাডাপ্টার আবার ব্যবহার করা যায়।
সহজ করা RemoteViews কালেকশন কীভাবে প্রয়োগ করবেন তার একটি উদাহরণ এখানে দেওয়া হল।
val itemLayouts = listOf( R.layout.item_type_1, R.layout.item_type_2, // ... ) remoteView.setRemoteAdapter( R.id.list_view, RemoteViews.RemoteCollectionItems.Builder() .addItem(/* id= */ ID_1, RemoteViews(context.packageName, R.layout.item_type_1)) .addItem(/* id= */ ID_2, RemoteViews(context.packageName, R.layout.item_type_2)) // ... .setViewTypeCount(itemLayouts.count()) .build() )