android 界面设计基本知识Ⅲ

  本章继续讲述在android界面设计中相关的知识点。介绍内容包括BroadcastReceiver(广播),Service(服务),Widget(小部件),WebView(网页加载控件)。

1.BroadcastReceiver

(1)广播简介

 在Android中,Broadcast是一种广泛运用的在应用程序之间传输信息的机制。而BroadcastReceiver是对发送出来的 Broadcast进行过滤接受并响应的一类组件。

广播接收者( BroadcastReceiver )用于接收广播 Intent ,广播 Intent 的发送是通过调用 Context.sendBroadcast() 、 Context.sendOrderedBroadcast() 来实现的。通常一个广播 Intent 可以被订阅了此 Intent 的多个广播接收者所接收。

(2)广播机制

  首先在需要发送信息的地方,把要发送的信息和用于过滤的信息(如Action、Category)装入一个Intent对象,然后通过调用 sendOrderBroadcast()或sendStickyBroadcast()方法,把 Intent对象以广播方式发送出去。

当Intent发送以后,所有已经注册的BroadcastReceiver会检查注册时的IntentFilter是否与发送的Intent 相匹配,若匹配则就会调用BroadcastReceiver的onReceive()方法。所以当我们定义一个BroadcastReceiver的时候,都需要实现onReceive()方法。

(3)广播注册

  • 静态注册:在AndroidManifest.xml中用标签生命注册,并在标签内用标签设置过滤器。例如:

  <receiver android:name="myRecevice">    //继承BroadcastReceiver,重写onReceiver方法

    <intent-filter>    

      <action android:name="com.dragon.net"></action> //使用过滤器,接收指定action广播

      </intent-filter>

  </receiver> 

  • 动态注册:

  IntentFilter intentFilter = new IntentFilter();

  intentFilter.addAction(String);   //为BroadcastReceiver指定action,使之用于接收同action的广播

      registerReceiver(BroadcastReceiver,intentFilter);

  一般:在onStart中注册,onStop中取消unregisterReceiver

  指定广播目标Action:Intent intent = new Intent(actionString);

  并且可通过Intent携带消息 :intent.putExtra("msg", "hi,我通过广播发送消息了");

2.Service

(1)服务简介

  A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service might handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.

  翻译过来就是:Service(服务)是一个没有用户界面的在后台运行执行耗时操作的应用组件。其他应用组件能够启动Service,并且当用户切换到另外 的应用场景,Service将持续在后台运行。另外,一个组件能够绑定到一个service与之交互(IPC机制),例如,一个service可能会处理 网络操作,播放音乐,操作文件I/O或者与内容提供者(content provider)交互,所有这些活动都是在后台进行。

Service有两种状态,“启动的”和“绑定”。Service生命周期流程如下图所示:

(2)启动方式

  • startService 启动的服务:主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService;
  • bindService 启动的服务:该方法启动的服务可以进行通信。停止服务使用unbindService;
  • startService 同时也 bindService 启动的服务:停止服务应同时使用stepService与unbindService

  绑定状态的service,通过调用bindService()来启动,一个绑定的service提供一个允许组件与service交互的接 口,可以发送请求、获取返回结果,还可以通过夸进程通信来交互(IPC)。绑定的service只有当应用组件绑定后才能运行,多个组件可以绑定一个 service,当调用unbind()方法时,这个service就会被销毁了。

(3)使用方法

注册Service,启动Service,在AndroidManifest.xml中注册,注册代码如下:

  <service android:name="com.example.trywidgetsimplest.MusicManageService" ></service

启动服务:

              Intent startIntent = new Intent(MainActivity.this,MusicManageService.class);  

              startService(startIntent); 

停止服务:

             Intent startIntent = new Intent(MainActivity.this,MusicManageService.class); 

             stopService(startIntent); 

绑定服务:

绑定服务,便于数据交互或者访问其中的一些方法:
        public boolean bindService(Intent intent, ServiceConnection conn, int flags) ;
        public void unbindService(ServiceConnection conn);
        intent是跳转到service的intent,如 Intent intent = new Intent();intent.setClass(this,MyService.class);
        conn则是一个代表与service连接状态的类,当我们连接service成功或失败时,会主动触发其内部的onServiceConnected或onServiceDisconnected方法。访问service中的数据,可以在onServiceConnected()方法中进行实现。

(4)注意事项

  • 在调用 bindService 绑定到Service的时候,应当保证在某处调用 unbindService 解除绑定(尽管 Activity 被 finish 的时候绑定会自动解除,并且Service会自动停止);
  • 使用 startService 启动服务之后,一定要使用 stopService停止服务,不管你是否使用bindService;
  • 使用 startService 与 bindService 要注意到,Service 的终止,需要unbindService与stopService同时调用,才能终止 Service,不管 startService 与 bindService 的调用顺序,如果先调用 unbindService 此时服务不会自动终止,再调用 stopService 之后服务才会停止,如果先调用 stopService 此时服务也不会终止,而再调用 unbindService 或者之前调用 bindService 的 Context 不存在了(如Activity 被 finish 的时候)之后服务才会自动停止;
  • 当在旋转手机屏幕的时候,当手机屏幕在“横”“竖”变换时,此时如果你的 Activity 如果会自动旋转的话,旋转其实是 Activity 的重新创建,因此旋转之前的使用 bindService 建立的连接便会断开(Context 不存在了),对应服务的生命周期与上述相同。

3.Widget

(1)Widget简介

  App Widget是应用程序窗口小部件(Widget)是微型的应用程序视图,它可以被嵌入到其它应用程序中(比如桌面)并接收周期性的更新。你可以通过一个App Widget Provider来发布一个Widget。

(2)Widget应用

appwidget-provider标签:

这个玩意是用来定义桌面widget的大小,初始状态等等信息的,它的位置应该放在res/xml文件夹下,具体的xml参数如下:

  • android:minWidth : 最小宽度
  • android:minHeight : 最小高度
  • android:updatePeriodMillis : 更新widget的时间间隔(ms),"86400000"为1个小时
  • android:previewImage : 预览图片
  • android:initialLayout : 加载到桌面时对应的布局文件
  • android:resizeMode : widget可以被拉伸的方向。horizontal表示可以水平拉伸,vertical表示可以竖直拉伸
  • android:widgetCategory : widget可以被显示的位置。home_screen表示可以将widget添加到桌面,keyguard表示widget可以被添加到锁屏界面
  • android:initialKeyguardLayout : 加载到锁屏界面时对应的布局文件

示例XML
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
  android:minWidth="40dp"
  android:minHeight="40dp"
  android:updatePeriodMillis="86400000"
  android:previewImage="@drawable/preview"
  android:initialLayout="@layout/example_appwidget"
  android:configure="com.example.android.ExampleAppWidgetConfigure" 
  android:resizeMode="horizontal|vertical"
  android:widgetCategory="home_screen|keyguard"
  android:initialKeyguardLayout="@layout/example_keyguard">
</appwidget-provider>

示例说明

  • minWidth 和minHeight

   它们指定了App Widget布局需要的最小区域。缺省的App Widgets所在窗口的桌面位置基于有确定高度和宽度的单元网格中。如果App Widget的最小长度或宽度和这些网格单元的尺寸不匹配,那么这个App Widget将上舍入(上舍入即取比该值大的最接近的整数)到最接近的单元尺寸。注意:app widget的最小尺寸,不建议比 “4x4” 个单元格要大。关于app widget的尺寸,后面在详细说明。

  • minResizeWidth 和 minResizeHeight  

  它们属性指定了 widget 的最小绝对尺寸。也就是说,如果 widget 小于该尺寸,便会因为变得模糊、看不清或不可用。 使用这两个属性,可以允许用户重新调整 widget 的大小,使 widget 的大小可以小于 minWidth 和 minHeight。注意:当 minResizeWidth 的值比 minWidth 大时,minResizeWidth 无效;当 resizeMode 的取值不包括 horizontal 时,minResizeWidth 无效。当 minResizeHeight 的值比 minHeight 大时,minResizeHeight 无效;当 resizeMode 的取值不包括 vertical 时,minResizeHeight 无效。

  • updatePeriodMillis  

   它定义了 widget 的更新频率。实际的更新时机不一定是精确的按照这个时间发生的。建议更新尽量不要太频繁,最好是低于1小时一次。 或者可以在配置 Activity 里面供用户对更新频率进行配置。 实际上,当updatePeriodMillis的值小于30分钟时,系统会自动将更新频率设为30分钟!关于这部分,后面会详细介绍。
  注意: 当更新时机到达时,如果设备正在休眠,那么设备将会被唤醒以执行更新。如果更新频率不超过1小时一次,那么对电池寿命应该不会造成多大的影响。 如果你需要比较频繁的更新,或者你不希望在设备休眠的时候执行更新,那么可以使用基于 alarm 的更新来替代 widget 自身的刷新机制。将 alarm 类型设置为 ELAPSED_REALTIME 或 RTC,将不会唤醒休眠的设备,同时请将 updatePeriodMillis 设为 0。

  • initialLayout   

  指向 widget 的布局资源文件

  • configure  

  可选属性,定义了 widget 的配置 Activity。如果定义了该项,那么当 widget 创建时,会自动启动该 Activity。

  • previewImage  

  指定预览图,该预览图在用户选择 widget 时出现,如果没有提供,则会显示应用的图标。该字段对应在 AndroidManifest.xml 中 receiver 的 android:previewImage 字段。由 Android 3.0 引入。

  • autoAdvanceViewId   

  指定一个子view ID,表明该子 view 会自动更新。在 Android 3.0 中引入。

  • resizeMode 

  指定了 widget 的调整尺寸的规则。可取的值有: "horizontal", "vertical", "none"。"horizontal"意味着widget可以水平拉伸,“vertical”意味着widget可以竖值拉伸,“none”意味着 widget不能拉伸;默认值是"none"。Android 3.1 引入。

  • widgetCategory   

  指定了 widget 能显示的地方:能否显示在 home Screen 或 lock screen 或 两者都可以。它的取值包括:"home_screen" 和 "keyguard"。Android 4.2 引入。

  • initialKeyguardLayout 

  指向 widget 位于 lockscreen 中的布局资源文件。Android 4.2 引入。

AppWidgetProvider类:

  通过appwidget-provider标签就可以得到初始化的布局,视图等,但widget要实时更新时,要响应用户操作时,就需要额外的类来辅助处理了,这个类就是AppWidgetProvider。由于AppWidgetProvider要接收到当前widget的状态(是否被添加,是否被删除等),所以要接收通知,必然是派生自BroadcastReceiver。

AppWidgetProvider中的广播处理函数如下:(根据不同的使用情况,重写不同的函数)

  • onUpdate():

  在3种情况下会调用OnUpdate()。onUpdate()是在main线程中进行,因此如果处理需要花费时间多于10秒,处理应在service中完成。(第二篇会讲为什么还要有service)

  1. 在时间间隔到时调用,时间间隔在widget定义的android:updatePeriodMillis中设置;
  2.   用户拖拽到主页,widget实例生成。无论有没有设置Configure activity,我们在Android4.4的测试中,当用户拖拽图片至主页时,widget实例生成,会触发onUpdate(),然后再显示 activity(如果有)。这点和资料说的不一样,资料认为如果设置了Configure acitivity,就不会在一开始调用onUpdate(),而实验显示当实例生成(包括创建和重启时恢复),都会先调用onUpate()。在本例, 由于此时在preference尚未有相关数据,创建实例时不能有效进行数据设置。
  3. 机器重启,实例在主页上显示,会再次调用onUpdate()
  • onDeleted(Context, int[]):

  当 widget 被删除时被触发。

  • onEnabled(Context):

  当第1个 widget 的实例被创建时触发。也就是说,如果用户对同一个 widget 增加了两次(两个实例),那么onEnabled()只会在第一次增加widget时触发。

  • onDisabled(Context):

  当最后1个 widget 的实例被删除时触发。

  • onReceive(Context, Intent):

  在接收到广播时,调用。

(3)Widget布局

  在 AppWidgetProviderInfo中已经介绍了,minWidth 和minHeight 用来指定了App Widget布局需要的最小区域。缺省的App Widgets所在窗口的桌面位置基于有确定高度和宽度的单元网格中。如果App Widget的最小长度或宽度和这些网格单元的尺寸不匹配,那么这个App Widget将上舍入(上舍入即取比该值大的最接近的整数——译者注)到最接近的单元尺寸。
例如,很多手机提供4x4网格,平板电脑能提供8x7网格。当widget被添加到时,在满足minWidth和minHeight约束的前提下,它将被占领的最小数目的细胞。

粗略计算minWidth和minHeight,可以参考下面表格:

单元格个数
(行 / 列)
对应的设置大小 (dp)
(minWidth / minHeight)
1 40dp
2 110dp
3 180dp
4 250dp
n 70 × n − 30

详细计算minWidth和minHeight,要计算各个区域的大小。以下图为例:

计算结果
minWidth = 144dp + (2 × 8dp) + (2 × 56dp) = 272dp
minHeight = 48dp + (2 × 4dp) = 56dp

(4)Widget支持的布局和控件

Widget并不支持所有的布局和控件,而仅仅只是支持Android布局和控件的一个子集。

  • App Widget支持的布局 

   FrameLayout

 LinearLayout

   RelativeLayout

  GridLayout

  •  App Widget支持的控件

  AnalogClock

  Button            

  Chronometer

  ImageButton

  ImageView

  ProgressBar

  TextView

  ViewFlipper

  ListView

  GridView

  StackView

  AdapterViewFlipper

除此之外的所有控件(包括自定义控件)都无法显示,无法显示时,添加出来的widget会显示“加载布局出错”

4.WebView

 

5.参考引用

Widget文档参考:

http://blog.csdn.net/harvic880925/article/details/41445407

http://blog.csdn.net/sasoritattoo/article/details/17616597

Service文档参考:

http://www.cnblogs.com/yejiurui/p/3429451.html

 

 

 

 

 

 

 

 

 

 

 

posted @ 2016-03-25 10:42  无涯Ⅱ  阅读(2377)  评论(0编辑  收藏  举报