<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## 5.1?`RemoteViews`的應用 (1)RemoteViews表示的是一個view結構,它可以在其他進程中顯示。由于它在其他進程中顯示,為了能夠更新它的界面,RemoteViews提供了一組基礎的操作用于跨進程更新它的界面。 (2)RemoteViews主要用于通知欄通知和桌面小部件的開發,通知欄通知是通過`NotificationManager`的`notify`方法來實現的;桌面小部件是通過`AppWidgetProvider`來實現的,它本質上是一個廣播(BroadcastReceiver)。這兩者的界面都是運行在`SystemServer`進程中。 (3)RemoteViews在Notification中的應用示例 ~~~ Notification notification = new Notification(); notification.icon = R.drawable.ic_launcher; notification.tickerText = "hello world"; notification.when = System.currentTimeMillis(); notification.flags = Notification.FLAG_AUTO_CANCEL; Intent intent = new Intent(this, DemoActivity_1.class); intent.putExtra("sid", "" + sId); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.layout_notification); remoteViews.setTextViewText(R.id.msg, "chapter_5: " + sId);//設置textview的顯示文本 remoteViews.setImageViewResource(R.id.icon, R.drawable.icon1); PendingIntent openActivity2PendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, DemoActivity_2.class), PendingIntent.FLAG_UPDATE_CURRENT); remoteViews.setOnClickPendingIntent(R.id.open_activity2, openActivity2PendingIntent);//給圖片添加點擊事件 notification.contentView = remoteViews; notification.contentIntent = pendingIntent; NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); manager.notify(sId, notification); ~~~ (4)RemoteViews在桌面小部件中的應用 1.定義小部件界面; 2.定義小部件配置信息:其中`updatePeriodMillis`定義小工具的自動更新周期,單位為ms。 ~~~ <?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialLayout="@layout/widget" android:minHeight="84dp" android:minWidth="84dp" android:updatePeriodMillis="86400000" > </appwidget-provider> ~~~ 3.定義小部件的實現類:書中的示例實現了一個顯示一張圖片的小部件,每次點擊小部件的時候圖片就會旋轉一周; ~~~ public class MyAppWidgetProvider extends AppWidgetProvider { public static final String TAG = "MyAppWidgetProvider"; public static final String CLICK_ACTION = "com.ryg.chapter_5.action.CLICK"; public MyAppWidgetProvider() { super(); } @Override public void onReceive(final Context context, Intent intent) { super.onReceive(context, intent); Log.i(TAG, "onReceive : action = " + intent.getAction()); // 這里判斷是自己的action,做自己的事情,比如小工具被點擊了要干啥,這里是做一個動畫效果 if (intent.getAction().equals(CLICK_ACTION)) { Toast.makeText(context, "clicked it", Toast.LENGTH_SHORT).show(); new Thread(new Runnable() { @Override public void run() { Bitmap srcbBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.icon1); AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); for (int i = 0; i < 37; i++) { float degree = (i * 10) % 360; RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget); remoteViews.setImageViewBitmap(R.id.imageView1, rotateBitmap(context, srcbBitmap, degree)); Intent intentClick = new Intent(); intentClick.setAction(CLICK_ACTION); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intentClick, 0); remoteViews.setOnClickPendingIntent(R.id.imageView1, pendingIntent); appWidgetManager.updateAppWidget(new ComponentName(context, MyAppWidgetProvider.class),remoteViews); SystemClock.sleep(30); } } }).start(); } } /** * 每次窗口小部件被點擊更新都調用一次該方法 */ @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { super.onUpdate(context, appWidgetManager, appWidgetIds); Log.i(TAG, "onUpdate"); final int counter = appWidgetIds.length; Log.i(TAG, "counter = " + counter); for (int i = 0; i < counter; i++) { int appWidgetId = appWidgetIds[i]; onWidgetUpdate(context, appWidgetManager, appWidgetId); } } /** * 窗口小部件更新 */ private void onWidgetUpdate(Context context, AppWidgetManager appWidgeManger, int appWidgetId) { Log.i(TAG, "appWidgetId = " + appWidgetId); RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget); // "窗口小部件"點擊事件發送的Intent廣播 Intent intentClick = new Intent(); intentClick.setAction(CLICK_ACTION); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intentClick, 0); remoteViews.setOnClickPendingIntent(R.id.imageView1, pendingIntent); appWidgeManger.updateAppWidget(appWidgetId, remoteViews); } private Bitmap rotateBitmap(Context context, Bitmap srcbBitmap, float degree) { Matrix matrix = new Matrix(); matrix.reset(); matrix.setRotate(degree); return Bitmap.createBitmap(srcbBitmap, 0, 0, srcbBitmap.getWidth(), srcbBitmap.getHeight(), matrix, true); } } ~~~ 4.在AndroidManifest.xml文件中聲明小部件 下面的示例中包含了兩個action,第一個action用于識別小部件的單擊行為,而第二個action是作為小部件必須存在的action?`android.appwidget.action.APPWIDGET_UPDATE`,如果不加那么就無法顯示小部件。 ~~~ <receiver android:name=".MyAppWidgetProvider" > <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget_provider_info" > </meta-data> <intent-filter> <action android:name="com.ryg.chapter_5.action.CLICK" /> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> </receiver> ~~~ (5)AppWidgetProvider會自動根據廣播的action通過`onReceive`方法來自動分發廣播,也就是調用下面不同的方法: `onEnable`:當小部件第一次添加到桌面時調用,小部件可以添加多次但是只在第一次添加的時候調用; `onUpdate`:小部件被添加時或者每次小部件更新時都會調用一次該方法,每個周期小部件都會自動更新一次; `onDeleted`:每刪除一次小部件就調用一次; `onDisabled`:當最后一個該類型的小部件被刪除時調用該方法; `onReceive`:這是廣播內置的方法,用于分發具體的事件給其他方法,所以該方法一般要調用`super.onReceive(context, intent);`?如果自定義了其他action的廣播,就可以在調用了父類方法之后進行判斷,如上面代碼所示。 (6)`PendingIntent`表示一種處于Pending狀態的Intent,pending表示的是即將發生的意思,它是在將來的某個不確定的時刻放生,而Intent是立刻發生。 (7)PendingIntent支持三種待定意圖:啟動Activity(getActivity),啟動Service(getService),發送廣播(getBroadcast)。 `PendingIntent.getActivity(Context context, in requestCode, Intent intent, int flags)` 獲得一個PendingIntent,當待定意圖發生時,效果相當于Context.startActivity(intent)。 第二個參數`requestCode`是PendingIntent發送方的請求碼,多數情況下設為0即可,另外requestCode會影響到flags的效果。 PendingIntent的匹配規則:如果兩個PendingIntent內部的Intent相同,并且requestCode也相同,那么這兩個PendingIntent就是相同的。 Intent的匹配規則:如果兩個Intent的ComponentName和intent-filter都相同,那么這兩個Intent就是相同的,Extras不參與Intent的匹配過程。 第四個參數flags常見的類型有:`FLAG_ONE_SHOT`、`FLAG_NO_CREATE`、`FLAG_CANCEL_CURRENT`、`FLAG_UPDATE_CURRENT`。 `FLAG_ONE_SHOT`:當前描述的PendingIntent只能被調用一次,然后它就會被自動cancel。如果后續還有相同的PendingIntent,那么它們的send方法就會調用失敗。對于通知欄消息來說,如果采用這個flag,那么同類的通知只能使用一次,后續的通知單擊后將無法打開。 `FLAG_NO_CREATE`:當前描述的PendingIntent不會主動創建,如果當前PendingIntent之前不存在,那么getActivity、getService和getBroadcast方法會直接返回null,即獲取PendingIntent失敗。這個標志位使用很少。 `FLAG_CANCEL_CURRENT`:當前描述的PendingIntent如果已經存在,那么它們都會被cancel,然后系統會創建一個新的PendingIntent。 對于通知欄消息來說,那些被cancel的通知單擊后將無法打開。 `FLAG_UPDATE_CURRENT`:當前描述的PendingIntent如果已經存在,那么它們都會被更新,即它們的Intent中的Extras會被替換成最新的。 (8)分析`NotificationManager.nofify(id, notification)`?[未測試,看著有點暈] 1.如果參數id是常量,那么多次調用notify只能彈出一個通知,后續的通知會把前面的通知完全替代掉; 2.如果參數id每次都不同,那么當PendingIntent不匹配的時候,不管采用何種標志位,這些通知之間不會相互干擾; 3.如果參數id每次都不同,且PendingIntent匹配的時候,那就要看標志位: 如果標志位是FLAG_ONE_SHOT,那么后續的通知中的PendingIntent會和第一條通知保持完全一致,包括其中的Extras,單擊任何一條通知后,剩下的通知均無法再打開,當所有的通知都被清除后,會再次重復這個過程; 如果標志位是FLAG_CANCEL_CURRENT,那么只有最新的通知可以打開,之前彈出的所有通知都無法打開; 如果標志位是FLAG_UPDATE_CURRENT,那么之前彈出的通知中的PendingIntent會被更新,最終它們和最新的一條通知保持完全一致,包括其中的Extras,并且這些通知都是可以打開的。 ## 5.2 RemoteViews的內部機制 (1)RemoteViews的構造方法?`public RemoteViews(String packageName, int layoutId)`,第一個參數是當前應用的包名,第二個參數是待加載的布局文件。 (2)RemoteViews只支持部分布局和View組件,下面列舉的組件的子類是不支持的 布局:`FrameLayout、LinearLayout、RelativeLayout、GridLayout` 組件:`Button、ImageButton、ImageView、TextView、ListView、GridView、ViewStub`等 (3)RemoteViews提供了一系列的set方法完成view的設置,這是通過反射完成的調用的。 例如方法`setInt(int viewId, String methodName, int value)`就是反射調用view對象的名稱為methodName的方法,傳入參數value,同樣的還有`setBoolean`、`setLong`等。 方法`setOnClickPendingIntent(int viewId, PendingIntent pi)`用來為view添加單擊事件,事件類型只能為PendingIntent。 (4)通知和小部件分別由`NotificationManager`和`AppWidgetManager`管理,而它們通過Binder分別和SystemServer進程中的`NotificationManagerService`和`AppWidgetManagerService`進行通信。所以,布局文件實際上是兩個Service加載的,運行在SystemServer進程中。 (5)RemoteViews實現了`Parcelable`接口,它會通過Binder傳遞到SystemServer進程,系統會根據RemoteViews中的包名信息獲取到應用中的資源,從而完成布局文件的加載。 (6)系統將view操作封裝成`Action`對象,Action同樣實現了Parcelable接口,通過Binder傳遞到SystemServer進程。遠程進程通過RemoteViews的`apply`方法來進行view的更新操作,RemoteViews的apply方法內部則會去遍歷所有的action對象并調用它們的apply方法來進行view的更新操作。 這樣做的好處是不需要定義大量的Binder接口,其次批量執行RemoteViews中的更新操作提高了程序性能。 (7)RemoteViews的`apply`和`reapply`方法的區別:`apply`方法會加載布局并更新界面,而`reapply`方法則只會更新界面。 (8)`setOnClickPendingIntent`、`setPendingIntentTemplate`和`setOnClickFillIntent`的區別 `setOnClickPendingIntent`用于給普通的view添加點擊事件,但是不能給集合(ListView和StackView)中的view設置點擊事件,因為開銷太大了。如果需要給ListView和StackView中的item添加點擊事件,需要結合`setPendingIntentTemplate`和`setOnClickFillIntent`一起使用。[并沒有嘗試(⊙o⊙)] ## 5.3 RemoteViews的意義 RemoteViews的最大的意義是實現了跨進程的UI更新,這節作者實現了一個模擬通知欄效果的應用來演示跨進程的UI更新,[源碼傳送門](https://github.com/singwhatiwanna/android-art-res/blob/master/Chapter_5/src/com/ryg/chapter_5/MainActivity.java)。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看