1.Android四大天王
1).Activity-负责应用程序中数据的显示.
2).Intent-运输大队长:传递应用程序当中所有数据.
3).Service-劳模:承担着大部分数据处理的工作.
4).Content Provider-国家档案馆:负责存储数据,并允许有需要的应用程序访问这些数据.
2. 开发工具: Android SDK+Eclipse
Android开发环境
1.Android SDK:
1)下载->安装->
2)添加Path环境变量 = D:\Android\Development\sdk\tools;
2.ADT的安装和配置(Android Developer Tools)
1)安装Java JDK,Eclipse
2)Eclipse->Preferences->Android->SDKLocation= D:\Android\Development\sdk
3.Android模拟器的配置
1)Android VirtualDevice Manager->创建AVD->选用相应的SDK版本
2)Start 运行这个AVD
HelloWorld to Android
1.创建一个Android应用程序的步骤:Newandroid application project
2.Android应用程序目录结构
1)gen包->R.java //自动生成的,有资源的ID
2)assets包->放资源文件,
3)res包->放资源文件,但都会在R.java中生成ID;
->layout:每个activity都有一个布局文件.相应的R.java中有相应的ID
3.AndroidManifest.xml:application配置文件
例如: icon="@drawable/ic_launcher" //相当于引用@drawble中的资源ic_launcher=0x7f020000
4.Android相关资源文件的作用
Activity初步
1.Activity的主要作用: 提供用户和应用程序交互的接口,可以添加各种控件(控件的容器).
2.创建一个Activity的方法.
1)一个Activity就是一个类,并且这个类继承Activity.
2)需要改写onCreate方法: Activity第一次调用的方法.
3)每个Activity都需要在AndroidManifest.xml文件中进行配置.
4)为Activity添加必要的控件: res->layout->activity_activity01.xml布局文件.
3.在AndroidManifest.xml文件当中注册应用activity的方法.
4.在Activity当中添加控件的方法:在res->layout->activity_activity01.xml布局文件中添加
5. 在Activity控件中,可以通过 findViewByID取得布局文件中所设置的控件.
Activity和Intent
1.多个Activity之间的关系: Activity01 通过startActivity(Intentintent)函数传递给另外一个Activity
2.Intent的基本作用:
一个Intent对象包含了一组信息:
1)Component name:指定启动哪一个activity
2)Action: 指定启动后我要做什么
3)Data: 想向另外一个activity传输的数据
4)Category:
5)Extras:key-values可以传输到另外一个activity
6)Flags
3.在一个Activity当中启动另外一个Activity的方法startActivity(Intent intent)
4.使用Intent在Activity之间传递数据的基本方法: 可以在不同的应用程序中的不同Activity之间传递数据
class MybuttonListener implementsOnClickListener {
@Override
public void onClick(Viewarg0) {
// TODO Auto-generated method stub
/* Intentintent = new Intent();
intent.putExtra("testintent","123");
intent.setClass(Activity02.this,OtherActivity.class);
Activity02.this.startActivity(intent);*/
Uri uri= Uri.parse("smsto://080000123");
Intentintent = new Intent(Intent.ACTION_SENDTO,uri);
intent.putExtra("sma_body", "The SMS text");
startActivity(intent);
}
}
控件使用方法:
1)TextVieW
2)EditText
3)Button
4)Menu
Activity生命周期
1.Task基本概念: a stack of activities.
1)应用程序启动之后,运行第一个Activity之后,该Activity对象被压入到stack中
2)点击按钮后启动第二个Activity,该Activity对象被压入到stack中
3)点击第二个Activity的按钮之后,启动第三个Activity,该Activity对象被压入到stack中
4)点击第三个Activity的按钮之后,启动第四个Activity
5)点击Back按钮,这是SMSActivity被从栈中弹出来……
2.Activity和Task之间的关系:
Task作用:可以把不同应用程序中的Activity组织在一起,在Stack中可以压入或弹出.
3.对话框风格的Activity的使用方法:
1)对话框风格的Activity和其他Activity的区别:是在AndroidManifest.xml文件中添加android:theme="@android:style/Theme.Dialog" />
Activity的布局初步
1.LinearLayout的使用方法
1)<?xml version="1.0" encoding="utf-8"?>, utf-8兼容中文显示.
2)padding:内边框
2.TableLayout的使用方法:
1)android:stretchColumns="1" //第一列作为拉伸的列
3. 内嵌布局
4. RelativeLayout4 类属性
1)将控件放置于给定ID的控件某个方向
android:layout_above="@+id/"
android:layout_below="@+id/"
android:layout_toLeftOf="@+id/"
android:layout_toRightOf="@+id/"
2)该控件的某个方向和
android:layout_alignLeft="@+id/"
android:layout_alignBaseline="@+id/"
android:layout_alignTop="@+id/"
android:layout_alignRight="@+id/"
android:layout_alignBottom="@+id/"
3)如果值为true,该控件和父控件在某个方向对齐
android:layout_alignParentLeft=""
android:layout_alignParentTop=""
android:layout_alignParentRight=""
android:layout_alignParentBottom=""
4)如果值为true,该控件位于某个方向
android:layout_centerHorizontal=""
android:layout_centerInParent=""
android:layout_centerVertical=""
############################################################################################################################
1. Radiogroup, Radiobutton
2. Toast
3. Progress Bar
4. ListView
###########################################################################################################################
Handle的使用
MessageQueue
在单线程模型下,为了解决类似的问题,Android设计了一个Message Queue(消息队列),线程间可以通过该Message Queue并结合Handler和Looper组件进行信息交换.
1.MessageQueue
Message Queue是一个消息队列,用来存放通过Handler发布的消息.消息队列通常附属于某一个创建它的线程,可以通过Looper.myQueue()得到当前线程的消息队列.如果没有消息队列对象则会抛出空指针异常.Android在第一次启动程序时会默认会为UI thread创建一个关联的消息队列,用来管理程序的一些上层组件,activities,broadcast receivers 等等.你可以在自己的子线程中创建Handler与UI thread通讯.也就是说我们程序一启动我们的UI线程也就是主线程就会有一个消息队列,而如果我们自己另外开启的一个子线程就不会有messageQueue(消息队列)对象,这一点大家务必知道.
2.Handler
通过Handler你可以发布或者处理一个消息或者是一个Runnable的实例.每个Handler都会与唯一的一个线程以及该线程的消息队列关联.当你创建一个新的Handler时候,默认情况下,它将关联到创建它的这个线程和该线程的消息队列.也就是说,如果你通过Handler发布消息的话,消息将只会发送到与它关联的这个消息队列,当然也只能处理该消息队列中的消息.这里大家就得理解一下了也就是说我们 一个Handler对应一个线程以及附属于该线程的消息队列.就比如我们现在有一个Handler对象这个Handler在UI线程中创建叫xh_Handler 那么我们根据上边的说明应该可以告诉我 这个xh_Handler是和那个线程关联的? 如果我用这个Handler发消息的话它将发给那个线程的消息队列?如果你知道了我想一般情况下你肯定是知道的.这时我们用这个Handler对象发送消息
Handler对象也可以发送消息哦,它有发送消息的方法.下面就说到了 待会大家看示例程序也会发现 主要就是看它怎么使用.
Handler的主要的方法有:
1)public final boolean sendMessage(Messagemsg)
把消息放入该Handler所关联的消息队列,放置在消息队列尾部.
这里请允许我多说一句就是我们把消息放进去的一端消息不会阻塞但是处理消息的一端就有可能会阻塞.欢迎收看看图频道.
2)public void handleMessage(Message msg)
关联该消息队列的线 程将通过调用Handler的handleMessage方 法来接收和处理消息,通常需要子类化Handler来 实现handleMessage。
public class TestBarHandler extends Activity {
/** Called when the activity is firstcreated. */
//声明控件变量
ProgressBarbar = null;
ButtonstartButton = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//根据控件的ID得到代表控件的对象,并为按钮设置监听器
bar = (ProgressBar)findViewById(R.id.bar);
startButton = (Button)findViewById(R.id.startButton);
startButton.setOnClickListener(newButtonListener());
}
//当点击startButton按钮时,就会执行ButtonListener的onClick方法
class ButtonListener implements OnClickListener{
@Override
public void onClick(View v) {
// TODOAuto-generated method stub
bar.setVisibility(View.VISIBLE);
updateBarHandler.post(updateThread);
}
}
//使用匿名内部类来复写Handler当中的handleMessage方法
Handler updateBarHandler = newHandler(){
@Override
public void handleMessage(Message msg) {
bar.setProgress(msg.arg1);
Bundlebundle = msg.getData();
updateBarHandler.post(updateThread);
System.out.println("test---->" + bundle.getString("test"));
}
};
//线程类,该类使用匿名内部类的方式进行声明
Runnable updateThread = newRunnable(){
int i = 0 ;
@Override
public void run() {
System.out.println("BeginThread" + i);
i = i + 10 ;
//得到一个消息对象,Message类是有Android操作系统提供
Messagemsg = updateBarHandler.obtainMessage();
//将msg对象的arg1参数的值设置为i,用arg1和arg2这两个成员变量传递消息,优点是系统性能消耗较少
msg.arg1 = i ;
Bundlebundle = new Bundle();
bundle.putString("test", "testbundle");
msg.setData(bundle);
try {
//设置当前显示睡眠1秒
Thread.sleep(1000);
}catch (InterruptedException e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
//将msg对象加入到消息队列当中
if( i > 100){
//如果当i的值为100时,就将线程对象从handler当中移除
updateBarHandler.removeCallbacks(updateThread);
System.out.println(">>>>>>");
}else{
updateBarHandler.sendMessage(msg);
System.out.println("<<<<<<");
}
}
};
Handle与线程的关系: Handle是和调用它的Activity是同一线程.
HandleThread 实现了looper(用于循环处理消息队列)
HandleTread.start()
Looper
Looper扮演着一个Handler和消息队列之间通讯桥梁的角色。程序组件首先通过Handler把消息传递给Looper,Looper把消息放入队列。Looper也把消息队列里的消息广播给所有的Handler,Handler接受到消息后调用handleMessage进行处理。
1) 可以通过Looper类的静态方法Looper.myLooper得到当前线程的Looper实例,如果当前线程未关联一个Looper实例,该方法将返回空(null)它不会抛空指针异常。
2) 可以通过静态方法Looper. getMainLooper方法得到主线程的Looper实例这里需要注意一下主线程默认是有一个Looper对象的。但是我们自己定义的子线程没有的。那么我们怎么在子线程中得到Looper对象呢?如果一个线程中调用Looper.prepare(),那么系统就会自动的为该线程建立一个消息队列,然后调用 Looper.loop();之后就进入了消息循环,这个之后就可以发消息、取消息、和处理消息。这个如何发送消息和如何处理消息可以再其他的线程中通过 Handle来做,但前提是我们的Hanle知道这个子线程的Looper,但是你如果不是在子线程运行 Looper.myLooper(),一般是得不到子线程的looper的。
##########################################################################################################################
1.Handler创建消息
每一个消息都需要被指定的Handler处理,通过Handler创建消息便可以完成此功能。Android消息机制中引入了消息池。Handler创建消息时首先查询消息池中是否有消息存在,如果有直接从消息池中取得,如果没有则重新初始化一个消息实例。使用消息池的好处是:消息不被使用时,并不作为垃圾回收,而是放入消息池,可供下次Handler创建消息时使用。消息池提高了消息对象的复用,减少系统垃圾回收的次数。消息的创建流程如图所示。
2.Handler发送消息
UI主线程初始化第一个Handler时会通过ThreadLocal创建一个Looper,该Looper与UI主线程一一对应。使用ThreadLocal的目的是保证每一个线程只创建唯一一个Looper。之后其他Handler初始化的时候直接获取第一个Handler创建的Looper。Looper初始化的时候会创建一个消息队列MessageQueue。至此,主线程、消息循环、消息队列之间的关系是1:1:1。
Handler、Looper、MessageQueue的初始化流程如图所示:
Hander持有对UI主线程消息队列MessageQueue和消息循环Looper的引用,子线程可以通过Handler将消息发送到UI线程的消息队列MessageQueue中。
3.Handler处理消息
UI主线程通过Looper循环查询消息队列UI_MQ,当发现有消息存在时会将消息从消息队列中取出。首先分析消息,通过消息的参数判断该消息对应的Handler,然后将消息分发到指定的Handler进行处理。
子线程通过 Handler 、 Looper 与 UI 主线程通信的流程如图所示