日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 之窗口小部件高级篇--App Widget 之 RemoteViews - 跨到对岸去

發(fā)布時(shí)間:2025/3/20 Android 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 之窗口小部件高级篇--App Widget 之 RemoteViews - 跨到对岸去 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? 在之前的一篇博文(?Android 之窗口小部件詳解--App Widge?t)中,已經(jīng)介紹了App Widget的基本用法和簡單實(shí)例。這篇主要講解 App Widget 的高級(jí)內(nèi)容,即通過 RemoteViews 去管理Widget的中GridView、ListView、StackView等內(nèi)容。在學(xué)習(xí)本篇之前,建議讀者先掌握 App Widget 的基本知識(shí)。

?

1 RemoteViews等相關(guān)類的介紹

下面先簡單介紹RemoteViews、RemoteViewsService、RemoteViewsFactory。

1.1 RemoteViews

? ? 顧名思義,它是一個(gè)遠(yuǎn)程視圖。App Widget中的視圖,都是通過RemoteViews表現(xiàn)的。?
? ? 在RemoteViews的構(gòu)造函數(shù)中,通過傳入layout文件的id來獲取 “l(fā)ayout文件對(duì)應(yīng)的視圖(RemoteViews)”;然后,調(diào)用RemoteViews中的方法能對(duì)layout中的組件進(jìn)行設(shè)置(例如,可以調(diào)用setTextViewText()來設(shè)置TextView組件的文本,可以調(diào)用setOnClickPendingIntent() 來設(shè)置Button的點(diǎn)擊響應(yīng)事件)。

? ? 因此,我們可以將 “RemoteViews 看作是 layout文件中所包含的全部視圖的集合”。

1.2 RemoteViewsService

? ? RemoteViewsService,是管理RemoteViews的服務(wù)。?
? ? 一般,當(dāng)App Widget 中包含“GridView、ListView、StackView等”集合視圖時(shí),才需要使用RemoteViewsService來進(jìn)行更新、管理。(集合視圖是指GridView、ListView、StackView等包含子元素的視圖)?
? ? RemoteViewsService更新“集合視圖”的一般步驟是:?
(01) 通過setRemoteAdapter來設(shè)置 “RemoteViews對(duì)應(yīng)RemoteViewsService”。?
(02) 之后在RemoteViewsService中,實(shí)現(xiàn)RemoteViewsFactory接口。然后,在RemoteViewsFactory接口中對(duì)“集合視圖”的各個(gè)子項(xiàng)進(jìn)行設(shè)置(“集合視圖”的各個(gè)子項(xiàng):例如,GridView的每一個(gè)格子都是一個(gè)子項(xiàng);ListView中的每一列也是一個(gè)子項(xiàng))。

? ? 因此,我們可以將 “RemoteViewsService 看作是 管理layout中集合視圖的服務(wù)”。

1.3 RemoteViewsFactory

? ? 通過RemoteViewsService中的介紹,我們可以了解“RemoteViewsService是通過RemoteViewsFactory來具體管理layout中集合視圖的”,即“RemoteViewsFactory管理集合視圖的實(shí)施者”。?
? ? RemoteViewsFactory是RemoteViewsService中的一個(gè)接口。RemoteViewsFactory提供了一系列的方法管理“集合視圖”中的每一項(xiàng)。例如:?
(01)RemoteViews getViewAt(int position)?
? ? ? 通過getViewAt()來獲取“集合視圖”中的第position項(xiàng)的視圖,視圖是以RemoteViews的對(duì)象返回的。?
(02)int getCount()?
? ? ? 通過getCount()來獲取“集合視圖”中所有子項(xiàng)的總數(shù)。

? ? 因此,我們可以將 “RemoteViewsFactory 看作是 layout中集合視圖管理的具體實(shí)施者”。

2 實(shí)例介紹

? ? 實(shí)現(xiàn)一個(gè)App Widget,App Widget可縮放,且包含“3個(gè)組成部分”。?
第1部分:是一個(gè)TextView文本,標(biāo)題內(nèi)容是“Sky Wang”。?
第2部分:是一個(gè)Button按鈕。點(diǎn)擊按鈕,會(huì)彈出一個(gè)Toast提示框,提示響應(yīng)了Button點(diǎn)擊事件。?
第3部分:是一個(gè)GridView視圖。GridView的每一個(gè)格子包含“圖片”和“文本”兩部分?jǐn)?shù)據(jù)。點(diǎn)擊GridView中的每一個(gè)格子,會(huì)彈出響應(yīng)的提示語。

manifest代碼如下?:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.skywang.test" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <receiver android:name=".GridWidgetProvider"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <!-- GridWidgetProvider接收點(diǎn)擊gridview的響應(yīng)事件 --> <action android:name="com.skywang.test.COLLECTION_VIEW_ACTION" /> <!-- GridWidgetProvider接收點(diǎn)擊bt_refresh的響應(yīng)事件 --> <action android:name="com.skywang.test.BT_REFRESH_ACTION" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_provider"/> </receiver> <service android:name=".GridWidgetService" android:permission="android.permission.BIND_REMOTEVIEWS" /> </application> </manifest>

說明:?
(01)?GridWidgetProvider.java?是?AppWidgetProvider的繼承類?,而且AppWidgetProvider的配置文件是?widget_provider.xml?。?
(02)?GridWidgetProvider.java?除了?響應(yīng) App Widget 的更新事件?(android.appwidget.action.APPWIDGET_UPDATE)之外;?
? ? ? ?也會(huì)“?響應(yīng)App Widget包含的GridView的點(diǎn)擊事件?(com.skywang.test.COLLECTION_VIEW_ACTION) ”??和“?App Widget包含的按鈕的點(diǎn)擊事件?(com.skywang.test.BT_REFRESH_ACTION) ”。?
(03)?GridWidgetService.java?是?RemoteViewsService的繼承類?。

widget_provider.xml代碼如下?:?
widget_provider.xml是AppWidgetProvider對(duì)應(yīng)配置文件

<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="180dp" android:minHeight="180dp" android:previewImage="@drawable/preview" android:initialLayout="@layout/widget_layout" android:resizeMode="horizontal|vertical" android:widgetCategory="home_screen"> </appwidget-provider>

說明:?
(01)?android:minWidth="180dp"?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 表明 "?Widget支持的最小寬度是3格?"?
(02)?android:minHeight="180dp"?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 表明 "?Widget支持的最小高度是3格?"?
(03)?android:initialLayout="@layout/widget_layout"?表明 "?Widget對(duì)應(yīng)的布局文件是widget_layout.xml?"?
(04)?android:previewImage="@drawable/preview" ? ??表明 "?Widget對(duì)應(yīng)的預(yù)覽圖片是preview.png?"?
(05)?android:resizeMode="horizontal|vertical" ? ? ? ? ??表明 "?Widget支持水平和豎直伸縮?"?
(06)?android:widgetCategory="home_screen"?? ? ? ? ? ?表明 "?Widget只能添加到桌面上,而不能添加到鎖屏界面上?"

?

widget_layout.xml代碼如下?:?
widget_layout.xml是App Widget的布局文件

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="8dip" android:layout_marginRight="8dip" > <TextView android:id="@+id/tv_head" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:gravity="left|center_vertical" android:textSize="24sp" android:text="SkyWang" /> <Button android:id="@+id/bt_refresh" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentRight="true" android:gravity="right|center_vertical" android:textSize="18sp" android:text="Refresh" /> </RelativeLayout> <GridView android:id="@+id/gridview" android:layout_width="match_parent" android:layout_height="match_parent" android:numColumns="auto_fit" android:verticalSpacing="4dip" android:horizontalSpacing="4dip" android:columnWidth="80dip" android:gravity="center" /> </LinearLayout>?

GridWidgetProvider.java代碼如下?:?
GridWidgetProvider.java是AppWidgetProvider的繼承類

package com.skywang.test;import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.util.Log; import android.widget.RemoteViews; import android.widget.Toast; import com.skywang.test.R; /** * @desc App Widget高級(jí)功能測試程序 * @author skywang * */ public class GridWidgetProvider extends AppWidgetProvider { private static final String TAG = "SKYWANG"; public static final String BT_REFRESH_ACTION = "com.skywang.test.BT_REFRESH_ACTION"; public static final String COLLECTION_VIEW_ACTION = "com.skywang.test.COLLECTION_VIEW_ACTION"; public static final String COLLECTION_VIEW_EXTRA = "com.skywang.test.COLLECTION_VIEW_EXTRA"; @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { Log.d(TAG, "GridWidgetProvider onUpdate"); for (int appWidgetId:appWidgetIds) { // 獲取AppWidget對(duì)應(yīng)的視圖 RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout); // 設(shè)置響應(yīng) “按鈕(bt_refresh)” 的intent Intent btIntent = new Intent().setAction(BT_REFRESH_ACTION); PendingIntent btPendingIntent = PendingIntent.getBroadcast(context, 0, btIntent, PendingIntent.FLAG_UPDATE_CURRENT); rv.setOnClickPendingIntent(R.id.bt_refresh, btPendingIntent); // 設(shè)置 “GridView(gridview)” 的adapter。 // (01) intent: 對(duì)應(yīng)啟動(dòng) GridWidgetService(RemoteViewsService) 的intent // (02) setRemoteAdapter: 設(shè)置 gridview的適配器 // 通過setRemoteAdapter將gridview和GridWidgetService關(guān)聯(lián)起來, // 以達(dá)到通過 GridWidgetService 更新 gridview 的目的 Intent serviceIntent = new Intent(context, GridWidgetService.class); rv.setRemoteAdapter(R.id.gridview, serviceIntent); // 設(shè)置響應(yīng) “GridView(gridview)” 的intent模板 // 說明:“集合控件(如GridView、ListView、StackView等)”中包含很多子元素,如GridView包含很多格子。 // 它們不能像普通的按鈕一樣通過 setOnClickPendingIntent 設(shè)置點(diǎn)擊事件,必須先通過兩步。 // (01) 通過 setPendingIntentTemplate 設(shè)置 “intent模板”,這是比不可少的! // (02) 然后在處理該“集合控件”的RemoteViewsFactory類的getViewAt()接口中 通過 setOnClickFillInIntent 設(shè)置“集合控件的某一項(xiàng)的數(shù)據(jù)” Intent gridIntent = new Intent(); gridIntent.setAction(COLLECTION_VIEW_ACTION); gridIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, gridIntent, PendingIntent.FLAG_UPDATE_CURRENT); // 設(shè)置intent模板 rv.setPendingIntentTemplate(R.id.gridview, pendingIntent); // 調(diào)用集合管理器對(duì)集合進(jìn)行更新 appWidgetManager.updateAppWidget(appWidgetId, rv); } super.onUpdate(context, appWidgetManager, appWidgetIds); } @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); Log.d(TAG, "GridWidgetProvider onReceive : "+intent.getAction()); if (action.equals(COLLECTION_VIEW_ACTION)) { // 接受“gridview”的點(diǎn)擊事件的廣播 int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); int viewIndex = intent.getIntExtra(COLLECTION_VIEW_EXTRA, 0); Toast.makeText(context, "Touched view " + viewIndex, Toast.LENGTH_SHORT).show(); } else if (action.equals(BT_REFRESH_ACTION)) { // 接受“bt_refresh”的點(diǎn)擊事件的廣播 Toast.makeText(context, "Click Button", Toast.LENGTH_SHORT).show(); } super.onReceive(context, intent); } }

說明:?
(01)?RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);?
? ? ?通過上面的語句,?獲取widget_layout.xml對(duì)應(yīng)的 RemoteViews?;進(jìn)而通過RemoteViews對(duì) widget_layout.xml中的各個(gè)元素進(jìn)行管理。?
(02)?rv.setOnClickPendingIntent(R.id.bt_refresh, btPendingIntent);?
? ? ?通過上面的語句,設(shè)置?點(diǎn)擊“按鈕(bt_refresh)”時(shí)會(huì)觸發(fā)的Intent?。從而對(duì)按鈕點(diǎn)擊事件進(jìn)行處理。?
(03)?rv.setRemoteAdapter(R.id.gridview, serviceIntent);?
? ? 通過上面的語句,?設(shè)置 “GridView(gridview)” 的遠(yuǎn)程適配器?,serviceIntent是 GridWidgetService 的Intent。?
? ? 從而在通過GridWidgetService對(duì)gridview進(jìn)行管理。?
(04)?PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, gridIntent, PendingIntent.FLAG_UPDATE_CURRENT);?
? ? 通過上面的語句,設(shè)置響應(yīng) “GridView(gridview)” 點(diǎn)擊事件的?intent模板?。關(guān)于“Intent模板”,后面在"?關(guān)于'GridView'的點(diǎn)擊事件?"會(huì)詳細(xì)說明。?
(05)?if (action.equals(COLLECTION_VIEW_ACTION)) ...?
? ? 通過上面的語句,響應(yīng)“GridView”的點(diǎn)擊事件。?
(06)?if (action.equals(BT_REFRESH_ACTION)) ...?
? ? 通過上面的語句,響應(yīng)“按鈕(bt_refresh)”的點(diǎn)擊事件。

?

關(guān)于 “GridView”的點(diǎn)擊事件。這里詳細(xì)說明以下!

? ? 像GridView這樣的集合控件,不能單單像按鈕一樣,通過setOnClickPendingIntent() 來設(shè)置它的點(diǎn)擊事件的Intent;而要通過以下兩步來進(jìn)行。?
? ??第一,設(shè)置GridView的點(diǎn)擊響應(yīng)事件的“Intent模板”。?
? ? ? ? ? ? ? 這是通過?setPendingIntentTemplate()?來進(jìn)行設(shè)置的。?
? ? ? ? ? ? ? 這樣做的目的有兩個(gè):首先,?設(shè)置Intent模板。?因?yàn)镚ridView有許多子項(xiàng),它們這些子項(xiàng)都?統(tǒng)一?的要響應(yīng)父親的?Intent模板?。其次,?傳遞附件參數(shù)(例如,App Widget的ID)?,因?yàn)锳pp Widget可以設(shè)置許多widget,每一個(gè)Widget的ID都不同,而且它們顯示的內(nèi)容可能不同(例如,不同大小的Widget顯示不同大小的文字)。?
? ? 第二,?設(shè)置GridView子項(xiàng)的點(diǎn)擊響應(yīng)事件的Intent。?
? ? ? ? ? ? ? 設(shè)置通過?setOnClickFillInIntent()?來進(jìn)行設(shè)置的。?
? ? ? ? ? ? ? 這樣做的首要目的,是?設(shè)置 GridView的子項(xiàng)所包含的信息?(例如,點(diǎn)擊的?GridView子項(xiàng)的索引值?)。?
? ? ? ? ? ? ? 通過這兩步的設(shè)置之后,點(diǎn)擊GridView中具體每一項(xiàng)的所產(chǎn)生的事件就是?“第一”和“第二”步中Intent的合集(組合)?。也就是說,?點(diǎn)擊“GridView中某一個(gè)子項(xiàng)”所產(chǎn)生的Intent,同時(shí)包含了“通過?setPendingIntentTemplate?傳遞的Intent數(shù)據(jù)”和“通過?setOnClickFillInIntent?傳遞的Intent數(shù)據(jù)”?。?理解這一點(diǎn)對(duì)理解這個(gè)RemoteView的原理至關(guān)重要!!!

GridWidgetService.java的代碼如下:

package com.skywang.test;import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.content.Context; import android.content.Intent; import android.widget.RemoteViews; import android.widget.RemoteViewsService; import android.util.Log; import java.util.List; import java.util.ArrayList; import java.util.HashMap; public class GridWidgetService extends RemoteViewsService{ private static final String TAG = "SKYWANG"; @Override public RemoteViewsService.RemoteViewsFactory onGetViewFactory(Intent intent) { Log.d(TAG, "GridWidgetService"); return new GridRemoteViewsFactory(this, intent); } private class GridRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory { private Context mContext; private int mAppWidgetId; private String IMAGE_ITEM = "imgage_item"; private String TEXT_ITEM = "text_item"; private ArrayList<HashMap<String, Object>> data ; private String[] arrText = new String[]{ "Picture 1", "Picture 2", "Picture 3", "Picture 4", "Picture 5", "Picture 6", "Picture 7", "Picture 8", "Picture 9" }; private int[] arrImages=new int[]{ R.drawable.p1, R.drawable.p2, R.drawable.p3, R.drawable.p4, R.drawable.p5, R.drawable.p6, R.drawable.p7, R.drawable.p8, R.drawable.p9 }; /** * 構(gòu)造GridRemoteViewsFactory * @author skywang */ public GridRemoteViewsFactory(Context context, Intent intent) { mContext = context; mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); Log.d(TAG, "GridRemoteViewsFactory mAppWidgetId:"+mAppWidgetId); } @Override public RemoteViews getViewAt(int position) { HashMap<String, Object> map; Log.d(TAG, "GridRemoteViewsFactory getViewAt:"+position); // 獲取 grid_view_item.xml 對(duì)應(yīng)的RemoteViews RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.grid_view_item); // 設(shè)置 第position位的“視圖”的數(shù)據(jù) map = (HashMap<String, Object>) data.get(position); rv.setImageViewResource(R.id.itemImage, ((Integer)map.get(IMAGE_ITEM)).intValue()); rv.setTextViewText(R.id.itemText, (String)map.get(TEXT_ITEM)); // 設(shè)置 第position位的“視圖”對(duì)應(yīng)的響應(yīng)事件 Intent fillInIntent = new Intent(); fillInIntent.putExtra(GridWidgetProvider.COLLECTION_VIEW_EXTRA, position); rv.setOnClickFillInIntent(R.id.itemLayout, fillInIntent); return rv; } /** * 初始化GridView的數(shù)據(jù) * @author skywang */ private void initGridViewData() { data = new ArrayList<HashMap<String, Object>>(); for (int i=0; i<9; i++) { HashMap<String, Object> map = new HashMap<String, Object>(); map.put(IMAGE_ITEM, arrImages[i]); map.put(TEXT_ITEM, arrText[i]); data.add(map); } } @Override public void onCreate() { Log.d(TAG, "onCreate"); // 初始化“集合視圖”中的數(shù)據(jù) initGridViewData(); } @Override public int getCount() { // 返回“集合視圖”中的數(shù)據(jù)的總數(shù) return data.size(); } @Override public long getItemId(int position) { // 返回當(dāng)前項(xiàng)在“集合視圖”中的位置 return position; } @Override public RemoteViews getLoadingView() { return null; } @Override public int getViewTypeCount() { // 只有一類 GridView return 1; } @Override public boolean hasStableIds() { return true; } @Override public void onDataSetChanged() { } @Override public void onDestroy() { data.clear(); } } }

說明:?
(01)?public RemoteViewsService.RemoteViewsFactory onGetViewFactory(Intent intent) ...?
? ? ? ?通過上面的語句,返回一個(gè)RemoteViewsFactory對(duì)象。?
? ? ? ?RemoteViewsService是一個(gè)服務(wù),通過之前對(duì)RemoteViewsService的介紹。我們知道,它 管理layout中集合視圖的服務(wù)。?
? ? ? ?RemoteViewsService管理layout中集合視圖的服務(wù),是通過 RemoteViewsFactory 實(shí)現(xiàn)的;那么它是如何實(shí)現(xiàn)的呢??
? ? ? ?RemoteViewsService是“通過 onGetViewFactory() 接口返回一個(gè) RemoteViewsFactory 對(duì)象” 來實(shí)現(xiàn)的。?
(02)?public void onCreate() ...?
? ? ? ?在onCreate()中進(jìn)行?RemoteViewsFactory 的初始化工作?。?
(03)?public int getCount() ...?
? ? ? ?通過getCount()返回?“集合視圖”中的數(shù)據(jù)項(xiàng)的總數(shù)。?
(04)?public RemoteViews getViewAt(int position) ...?
? ? ? ?通過上面的語句,返回?一個(gè)“集合視圖”中具體每一項(xiàng)的視圖。?
? ? ? ?getViewAt()是非常重要的函數(shù)!?我們對(duì)"集合視圖"中每一項(xiàng)的初始化都是在getViewAt()中進(jìn)行設(shè)置的?。?

grid_view_item.xml的代碼如下:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/itemLayout" android:layout_height="match_parent" android:layout_width="match_parent"> <ImageView android:id="@+id/itemImage" android:layout_width="80dip" android:layout_height="60dip" android:layout_centerHorizontal="true" android:scaleType="fitXY" /> <TextView android:id="@+id/itemText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/itemImage" android:layout_centerHorizontal="true" android:text="TextView01"/> </RelativeLayout>

點(diǎn)擊下載:?源代碼

點(diǎn)擊查看更多內(nèi)容:?
1.?Android 之窗口小部件詳解--App Widget?
2.?sky wang博客索引

實(shí)例效果圖:

?

轉(zhuǎn)載于:https://www.cnblogs.com/Free-Thinker/p/4422415.html

總結(jié)

以上是生活随笔為你收集整理的Android 之窗口小部件高级篇--App Widget 之 RemoteViews - 跨到对岸去的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。