4.Android Components
a) Content Provider (跨进程私有数据共享)
b) Service (长时间的后台耗时操作)
c) BroadCastReceiver(实现一对多的跨进程数据传递)
d) Activity(呈现view,实现与用户交互)
e) 关联组件(Fragment,Intent,Application)
Listview特殊属性
首先是stackFromBottom属性,这只该属性之后你做好的列表就会显示你列表的最下面,值为true和false
android:stackFromBottom="true"
第二是transciptMode属性,需要用ListView或者其它显示大量Items的控件实时跟踪或者查看信息,并且希望最新的条目可以自动滚动到可视范围内。通过设置的控件transcriptMode属性可以将Android平台的控件(支持ScrollBar)自动滑动到最底部。
android:transcriptMode="alwaysScroll"
第三cacheColorHint属性,很多人希望能够改变一下它的背景,使他能够符合整体的UI设计,改变背景背很简单只需要准备一张图片然后指定属性 android:background="@drawable/bg",不过不要高兴地太早,当你这么做以后,发现背景是变了,但是当你拖动,或者点击list空白位置的时候发现ListItem都变成黑色的了,破坏了整体效果。
如果你只是换背景的颜色的话,可以直接指定android:cacheColorHint为你所要的颜色,如果你是用图片做背景的话,那也只要将android:cacheColorHint指定为透明(#00000000)就可以了
第四divider属性,该属性作用是每一项之间需要设置一个图片做为间隔,或是去掉item之间的分割线
android:divider="@drawable/list_driver" 其中 @drawable/list_driver 是一个图片资源,如果不想显示分割线则只要设置为android:divider=“@null" 就可以了
第五fadingEdge属性,上边和下边有黑色的阴影
android:fadingEdge="none" 设置后没有阴影了~
第六scrollbars属性,作用是隐藏listView的滚动条,
android:scrollbars="none"与setVerticalScrollBarEnabled(true);的效果是一样的,不活动的时候隐藏,活动的时候也隐藏
第七fadeScrollbars属性,android:fadeScrollbars="true" 配置ListView布局的时候,设置这个属性为true就可以实现滚动条的自动隐藏和显示。
第八fastScrollEnabled属性 ,
很多开发者不知道ListView列表控件的快速滚动滑块是如何启用的,这里Android开发网告诉大家,辅助滚动滑块只需要一行代码就可以搞定,如果你使用XML布局只需要在ListView节点中加入 android:fastScrollEnabled="true" 这个属性即可,而对于Java代码可以通过myListView.setFastScrollEnabled(true); 来控制启用,参数false为隐藏。 还有一点就是当你的滚动内容较小,不到当前ListView的3个屏幕高度时则不会出现这个快速滚动滑块,同时该方法仍然是AbsListView的基础方法,可以在ListView或GridView等子类中使用快速滚动辅助。
第九drawSelectorOnTop属性
When set to true, the selector will be drawn over the selecteditem. Otherwise the selector is drawn behind the selected item. Thedefault value is false.
android:drawSelectorOnTop="true" 点击某一条记录,颜色会显示在最上面,记录上的文字被遮住,所以点击文字不放,文字就看不到
android:drawSelectorOnTop="false"点击某条记录不放,颜色会在记录的后面,成为背景色,但是记录内容的文字是可见的
class Message{
Object obj;数据
int what; 数据要用于做什么
.....
}
class MessageQueue{
Object[] message=new Object[5];
public void put(Message msg){}
public Message tabke(){}
}
class Looper{
private MessageQueue msgQ;
public void loop(){
while(true){....}
}
}
class Handler{
public void sendMessage(Message msg){}
public void handleMessage(Message msg){}
}
屏幕尺寸 DPI 应用内存
small / normal / large ldpi / mdpi 16MB
small / normal / large tvdpi / hdpi 32MB
small / normal / large xhdpi 64MB
small / normal / large 400dpi 96MB
small / normal / large xxhdpi 128MB
xlarge mdpi 32MB
xlarge tvdpi / hdpi 64MB
xlarge xhdpi 128MB
xlarge 400dpi 192MB
xlarge xxhdpi 256MB
监听ContentProvider中数据的变化
如果ContentProvider的访问者需要知道ContentProvider中的数据发生变化,可以在ContentProvider发生数据变化时调用getContentResolver().notifyChange(uri, null)来通知注册在此URI上的访问者
如果ContentProvider的访问者需要得到数据变化通知,必须使用ContentObserver对数据(数据采用uri描述)进行监听,当监听到数据变化通知时,系统就会调用ContentObserver的onChange()方法
ContentProvider的内部原理
自定义一个ContentProvider,来实现内部原理
步骤:
1、定义一个CONTENT_URI常量(里面的字符串必须是唯一)
Public static final Uri CONTENT_URI = Uri.parse("content://com.WangWeiDa.MyContentprovider");
如果有子表,URI为:
Public static final Uri CONTENT_URI = Uri.parse("content://com.WangWeiDa.MyContentProvider/users");
2、定义一个类,继承ContentProvider
Public class MyContentProvider extends ContentProvider
3、实现ContentProvider的所有方法(query、insert、update、delete、getType、onCreate)
package com.WangWeiDa.cp;
尽管这种查询字符串格式很常见,但是它看起来还是有点令人迷惑。为此,Android提供一系列的帮助类(在android.provider包下),里面包含了很多以类变量形式给出的查询字符串,这种方式更容易让我们理解一点,因此,如上面content://contacts/people/45这个URI就可以写成如下形式:
Uri person = ContentUris.withAppendedId(People.CONTENT_URI, 45);
然后执行数据查询:
Cursor cur = managedQuery(person, null, null, null);
Cursor cur = managedQuery(
mContacts,
columns, // 要返回的数据字段
null, // WHERE子句
null, // WHERE 子句的参数
null // Order-by子句
);
PS:
java.security.MessageDigest类用于为应用程序提供信息摘要算法的功能,如 MD5 或 SHA 算法。
扩展:Activity中finish() onDestroy() 和System.exit()的区别
Activity.finish()
Call this when your activity is done and should be closed.
在你的activity动作完成的时候,或者Activity需要关闭的时候,调用此方法。
当你调用此方法的时候,系统只是将最上面的Activity移出了栈,并没有及时的调用onDestory()方法,其占用的资源也没有被及时释放。因为移出了栈,所以当你点击手机上面的“back”按键的时候,也不会再找到这个Activity。
Activity.onDestory()
the system is temporarily destroying this instance of the activity to save space.
系统销毁了这个Activity的实例在内存中占据的空间。
在Activity的生命周期中,onDestory()方法是他生命的最后一步,资源空间等就被回收了。当重新进入此Activity的时候,必须重新创建,执行onCreate()方法。
System.exit(0)
这玩意是退出整个应用程序的,是针对整个Application的。将整个进程直接KO掉。
案例:Android开发之MdiaPlayer详解
MediaPlayer类可用于控制音频/视频文件或流的播放,我曾在《Android开发之基于Service的音乐播放器》一文中介绍过它的使用。下面让我们看一下MediaPlayer类的详细介绍。
一、类结构:
很多时候,你可能会问,为什么要用 Service,而不用 Thread 呢,因为用 Thread 是很方便的,比起 Service 也方便多了,下面我详细的来解释一下。
1). Thread:Thread 是程序执行的最小单元,它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作。
2). Service:Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。如果是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上。因此请不要把 Service 理解成线程,它跟线程半毛钱的关系都没有!
代码中注册广播:
注册广播方法一: registerReceiver(BroadcastReceiver receiver, IntentFilter filter) ,第一个参数是我们要处理广播的 BroadcastReceiver (广播接收者,可以是系统的,也可以是自定义的);第二个参数是意图过滤器。
注册广播方法二: registerReceiver(receiver, filter, broadcastPermission, scheduler) ,第一个参数是 BroadcastReceiver (广播接收者,可以是系统的,也可以是自定义的);第二个参数是意图过滤器;第三个参数是广播权限;第四个参数是 Hander ;
注意:权限重复现象,如果功能清单文件里注册了权限,在该方法再注册,则 receiver 无法收到广播,如果 功能清单文件里没有注册了权限,该方法注册也无法收到。当该方法没有注册权限,功能清单里注册的时候, receiver 能收到广播。
总结:在 Activity 中代码注册广播建议在: onResume() 中注册;
思维拓展: 1 ,如果在代码调用 registerReceiver(BroadcastReceiver receiver, IntentFilter filter) 十次( receiver , filter 的参数是同一参数),那么是否当该广播发送来的时候会收到十次呢?
2 ,注销是否也要注销十次才能把广播全部注销呢?
BroadCastReceiver 的 API
abortBroadcast ():
这个方法可以截获由 sendOrderedBroadcast () 发送来的 广播,让其它广播接收者无法收到这个广播。
clearAbortBroadcast ()
这个方法是针对上面的 abortBroadcast() 方法的,用于取消截获广播。这样它的下一级广播接收者就能够收到该广播了。
getAbortBroadcast ()
这个方法作用是:判断是否调用了 abortBroadcast (),如果先调用 abortBroadcast (),接着再调用 getAbortBroadcast (),将返回 true; 如果在调用 abortBroadcast() 、 clearAbortBroadcast ()
getAbortBroadcast (),将返回 false;
public final boolean getDebugUnregister ()
Since: API Level 1
Return the last value given to setDebugUnregister(boolean) .
getResultCode ()
如果用下面四个方法发送得广播,返回码为: -1 ;
// sendBroadcast(intent);
// sendBroadcast(intent, receiverPermission);
// sendOrderedBroadcast(intent, receiverPermission);
// sendStickyBroadcast(intent);
如果用下面两个方法发送得广播,返回码为:根据你设置 initialCode 的数字是多少就是多少;
// sendStickyOrderedBroadcast(intent, resultReceiver, scheduler,
// initialCode, initialData, initialExtras)
// sendOrderedBroadcast(intent, receiverPermission, resultReceiver,
// scheduler, initialCode, initialData, initialExtras)
getResultData ()
得到发送广播时设置的 initialData 的数据;
getResultExtras (boolean makeMap)
If true then a new empty Map will be made for you if the current Map is null; if false you should be prepared to receive a null Map.
得到由
sendStickyOrderedBroadcast(intent, resultReceiver, scheduler,
// initialCode, initialData, initialExtras) ;
// sendOrderedBroadcast(intent, receiverPermission, resultReceiver,
// scheduler, initialCode, initialData, initialExtras)
中 initialExtras 传入的参数。
实验:我用上面两个方法发了 initialExtras (这个一个 Bundle )传入的参数时,只要不为空,那么 makeMap 是否为 true 和 false 都能够得到数据。
isInitialStickyBroadcast ()
Returns true if the receiver is currently processing the initial value of a sticky broadcast -- that is, the value that was last broadcast and is currently held in the sticky cache, so this is not directly the result of a broadcast right now.
如果广播接收者是目前处理的一个宿主的广播的初始值,将返回 true , - 也就是说,这个值是最后的广播出的值,目前正在举行的宿主缓存,所以这并不是直接导致了现在的广播。
实验:在第三个应用中调用这个方法,无论你用哪种方式发送广播,这个方法得到的总是 false ;在发送广播 的 resultReceiver 广播接收者里面调用,得到的也是 false ;
isOrderedBroadcast ()
sendStickyOrderedBroadcast(intent, resultReceiver, scheduler, initialCode, initialData, initialExtras)
上面这个方法发送时,得到的是 true;
判断是否是有序广播;
d) Activity(呈现view,实现与用户交互)
***Activity 组件?Day19-3
这端话的意思就是说:当你进入一个应用时,开辟了A任务,然后当点击一个启动模式为singleInstance的Activity B 的时候,那么该Activity B 就一定会开辟任务B,然后在从该Activity B 启动其他 Activity C 的时候,那么就会判断Activity C 的亲族值和任务B的亲族值(其实就是Activity B 的亲族值)是否相同,如果相同,Activity C 就会在B任务中创建,否则开辟任务C,作为根Activity来创建实例。
6.Activity 的亲族设置?
Interface for classes whose instances can be written to and restored from a Parcel。 Classes implementing the Parcelable interface must also have a static field called CREATOR, which is an object implementing the Parcelable.Creator interface。
public interface Parcelable
{
//内容描述接口,基本不用管
public int describeContents();
//写入接口函数,打包
public void writeToParcel(Parcel dest, int flags);
//读取接口,目的是要从Parcel中构造一个实现了Parcelable的类的实例处理。因为实现类在这里还是不可知的,所以需要用到模板的方式,继承类名通过模板参数传入
//为了能够实现模板参数的传入,这里定义Creator嵌入接口,内含两个接口函数分别返回单个和多个继承类实例
public interface Creator<T>
{
public T createFromParcel(Parcel source);
public T[] newArray(int size);
}
}
实现Parcelable步骤
public static final Parcelable.Creator<T> CREATOR注:其中public static final一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写。需重写本接口中的两个方法:createFromParcel(Parcel in) 实现从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层,newArray(int size) 创建一个类型为T,长度为size的数组,仅一句话即可(return new T[size]),供外部类反序列化本类数组使用。
public class Person implements Serializable
{
private static final long serialVersionUID = -7060210544600464481L;
private String name;
private int age;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
}2)创建Book类,实现Parcelable
public class Book implements Parcelable
{
private String bookName;
private String author;
private int publishDate;
public Book()
{
}
public String getBookName()
{
return bookName;
}
public void setBookName(String bookName)
{
this.bookName = bookName;
}
public String getAuthor()
{
return author;
}
public void setAuthor(String author)
{
this.author = author;
}
public int getPublishDate()
{
return publishDate;
}
public void setPublishDate(int publishDate)
{
this.publishDate = publishDate;
}
@Override
public int describeContents()
{
return 0;
}
@Override
public void writeToParcel(Parcel out, int flags)
{
out.writeString(bookName);
out.writeString(author);
out.writeInt(publishDate);
}
public static final Parcelable.Creator<Book> CREATOR = new Creator<Book>()
{
@Override
public Book[] newArray(int size)
{
return new Book[size];
}
@Override
public Book createFromParcel(Parcel in)
{
return new Book(in);
}
};
4.Android Components
a) Content Provider (跨进程私有数据共享)
b) Service (长时间的后台耗时操作)
c) BroadCastReceiver(实现一对多的跨进程数据传递)
d) Activity(呈现view,实现与用户交互)
e) 关联组件(Fragment,Intent,Application)