1.新创建的android工程下的res/layout 目录下的xml文件为配置整个界面布局,而res/values/strings.xml 文件是指定了一些字符串的,可用于在界面上显示。这带来一个好处,我们可以这样为不同语言设置一个stringsxml文件,如中文,英文版。这样界面上所显示的内容根据不同的strings.xml 就可以动态的变换,也就是实现了本地化。


2.在res/layout/testmain.xml文件中引用strings.xml文件内容的方法:<Button android:text="@string/button_send">

<1> @代表了引用strings.xml文件中的字符串

<2> string代表引用资源的类型

<3> / 作为一个分隔字符串的名字

<4> 字符串的名字(相当于变量名字)


相应的在strings.xml中一定有一行:<string name="button_send">sendmymessage</string>

sendmymessage 这个就是button_send这个变量的内容


3.在layout下的xml文件中可以使用的控件:

<1> <EditText ..../>
<2> <Button ... />
<3> <TextView .../>


4.  从A activity启动一个B activity.

<1> startActivity(intent)

可以让参数intent携带数据,从A 传送到 B。方法:intetnt.putExtra(....);


<2>startActivityForResult()

这个函数不仅可以从A activity启动B avtivity 并且从A传送数据到B ,还可以从B返回数据到A。

当A启动了B,B完成了自己的事情返回时,系统会调用A中的函数:

protected void onActivityResult( int requestCode, int resultCode , Intent data);

其中requestCode是startActivityForResult()的参数传入的。

resultCode是有B activity设置的。

data是从B返回到A的数据。


5.Back stack

当从A activity 启动 B activity ,这时会将A停止,然后将A放入到“back stack”中,这个栈遵循“后进,先出”的顺序。当从B返回时,这时执行弹栈操作,将A从“back stack”弹出,显示给用户。


6.<intent-filter>

<activity> 下的 <intent-filter>的作用是为了让别的app使用隐式的intent来调用我们的activity,只要满足了该activity的 <intent-filter>条件.


7.activity分为两类,一类是显式的,一类是隐式的。

<1> 显式的启动

//Intent的第一个参数指定的是:源activity对应的类。 第二个参数指定的是:目的(启动)activity对应的类。
Intent intent = new Intent(this, SignInActivity.class);
//启动
startActivity(intent);


<2>隐式的启动

作用:当我们的应用程序没有实现某些功能,比如照相,我们可以调用照相程序拍摄一张照片,在将照片数据返回到我们的应用程序使用。我们创建一个intent,指定我们需要的action,然后系统替我们需找合适的activity来启动它,如果有多个activity适用,会让我们去选择使用哪一个.


代码(发送email):


//指明了action的类型为ACTION_SEND
Intent intent = new Intent(Intent.ACTION_SEND);
//让intent去携带了email的地址信息,让recipientArray储存地址。
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);


8.activity的生命周期

activity的生命周期就是不同状态的变换,对于每一种状态都有对应的回调函数可以供我们重写,来做出相应的控制。

如下:

onCreate
onStart()
onResume()
onPause()
onStop()
onDestroy()

注:你实现上面的这些生命周期的方法之前必须调用它们 父类 的相同方法,如上所示。

<1>OnCreate()

当activity第一次创建时,会调用此方法。其中是activity进行初始化的地方,分配资源什么的。注意:一定在这里调用 setContentView() 来设置activity的布局。


<2>OnStart()

当activity对于用户可见时,会调用此方法。


<3>OnRestart()

当activity已经被停止的时候。


<4>OnResume()

在activity开始于用户交互之前调用。这时,activity处于栈的顶端,伴随着用户的输入即将到达。


<5>OnPause()

在系统正要唤醒其他activityde的时候。


<6>OnStop()

当activity已经对于用户不可见的时候调用该函数。


<7>OnDestory()


9.隐式activity

<1>Intent的Action, Category 属性都是一个普通的字符串。

<2>每个intent都只能指定一个Action , 一个Category 属性。

<3>而对于AndroidManifest.xml中的Activity 配置下的<activity.../>的子元素<intent-filter.../>中可以指定多个Action,Category属性。

<4>匹配规则,只要intent中的Action和Category属性满足了<intent-filter.../>其中的一条Action和一条Category属性(两个属性同时满足),那么该activity就作为备选

可以被启动.

<5>intent默认的Category属性是:android.intent.category.DEFAULT.  设置category的函数: intent.addCategory(...)

<6>intent没有默认的Action. 设置action函数: intent.setAction(..)

<7>例子

public final static String TEST_ACTION = "com.example.test.TEST_ACTION";
......
Intent intent = new Intent();
intent.setAction(TEST_ACTION);
startActivity(intent);
......

<activity android:name=".SecondActivity" android:label="@string/app_name">
  <intent-filter>
    <action android:name="com.example.test.TEST_ACTION"/>
    <action andriod:name="com.example.test.HELLO_WORLD"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <catrgory android:name="android.intent.catrgory.LAUNCHER"/>
  </intent-fileter>
</activity>

解释:可以看到在<intent-fileter>中有多条actionhe category,只要各满足一条就可以启动该SecondActivity了。



10.引用资源

java的资源放在assets和res目录下,对于放在res目录下的资源,编译器会生成一个R类作为索引项用于代表其中的资源。

<1>java代码中引用资源

格式:R.资源类型.资源名字

例子:R.id.msg    R.string.app_name   R.layout.main_layout


<2>xml文件中引用资源

格式:@资源类型/资源名字

例子:@id/msg    @string/app_name


11.activity的生命期测试

情形:共有两个activity:A 和 B ,A是入口activity并且重载了:

OnCreate() . onStart() . onRestart() . onResume() . onPause() . onStop() . onDestroy()


输出调用函数:

<1>启动应用

OnCreate()

onStart()

onResume()


<2>从 A 启动 B

onPause()

onStop()


<3>从B 返回到 A

onRestart()

onStart()

onResume()


<4>从A 返回到主界面

onPause()

onStop()


<5>找到应用再次启动

onRestart()

onStart()

onResume()


<6>调用finishi()结束程序

onPause()

onStop()

onDestroy()


<7>直接从任务管理器结束程序

onDestroy()


12.安装应用程序在外存或者内存

android:installLocation; 

<pre class="prettyprint"><span class="tag"><manifest</span><span > </span><span class="atn">xmlns:android</span><span >=</span><span class="atv">"http://schemas.android.com/apk/res/android"</span><span >
    </span><span class="atn">android:installLocation</span><span >=</span><span class="atv">"preferExternal"</span><span >
    ... </span><span class="tag">></span>



它的值可以是:

<1>preferExternal

  让系统安装应用在外存,但是当外存空间满了之后,就将安装在内存中。

<2>auto

  让系统自己决定安装应用的位置

13. Android的Task和activity

<1>Task

  (1)每一个应用程序是一个Task,我们可以在Task之间进行切换,一个Task中包含多个activity.

  (2)当从A task切换到B task时,A被切换到后台并失去焦点,B被切换到前台获得焦点;且A中的back stack所有activity都会被暂停,B中处于back stack顶部的activity被唤醒,显示给用户进行交互。

  (3)每个task都拥有自己的back stack

<2>activity

  (1)activity被放在back stack中。

  (2)back stack遵循先进后出的原则。且其中的activity的顺序不会再改变,只能操作弹出与压入,不会有处于中间的2个activity互换位置。

  (3)处于back stack顶部的activity才会显示给用户交互

  (4)从A activity启动 B activity ,然后B acitity 启动 C activity。此时back stack中是:A处于最低部,B处于中间,C处于顶端。 这时从C 返回到 B,C被销毁释放掉,B从stack中弹出到顶端,显示给用户。

  (5)A 切换到 B,A的各种状态将被保存下来不会丢失掉。

  (6) 如果我们可以从B 和 C 都可以启动A,那么就有一种情况值得注意。列子,back stack中是(从底部到顶部):A,B,C。 此时因为我们可以从C启动A,那么这时会发生什么呢?两种情况考虑:

此条违反了back stack中的activity顺序不会改变原则)

  情况二:此时重新生成一个A的新实例放在back stack的顶端。

情况二。此时就存在了2个A的实例,但是我们可限制产生多个实例,具体请看官网文档。

14.保存Activity的状态

  情形:当我们从A activity启动到 B activity 。此时系统默认会为我们保存A的状态,但是当内存不足的时候,系统会完全的销毁掉A。然后我们从B返回到A时(虽然A已经被销毁掉,但back stack中任然有A的记录),此时系统会重新创建一个A acitivty,先前的状态也自然而然的丢失了,所以我们就要自己保存A的状态。

  处理:在onSaveInstanceState()回调方法中。

15.控件的事件传递流程

<1>当某组件所发生的事情不仅可以激发该组件的回调方法,而且会触发该组件所在的Activity的回调方法。(前提:该事件要能传播到该Activity)

<2>回调事件的处理方法几乎都有一个boolean类型的返回值,该返回值用于标示该事件能否进行传播。

  返回true: 表示该事件不能再传播

  返回false: 表示该事件可以进行传播

<3>当我们重写了:(1)控件的监听事件 (2)控件的回调函数 (3)控件所在activity的回调函数

这时调用的顺序是(前提事件可以进行传播,即这是三个函数都返回false):(1)-> (2)-> (3)

16.线程进行通讯

<1>原因:因为只有UI线程才能操作界面上的元素。所以我们自己创建的线程想要操作界面,就必须将相关数据传送给UI线程。

<2>通讯的工具:使用Handler作为载体,发送和接受消息。它发送的消息会放在MessageQueue队列中。

<3>通讯前提:拥有MessageQueue, 并且拥有MessageQueue的前提是有Looper对象,Looper对象对MessageQueue中的消息进行管理。

  (1)主UI线程已经初始化了一个Looper对象,所以直接可以用Handler

  (2)新创建的线程是没有Looper对象的,所以我们必须自己创建。

<4>通讯流程

  (1)调用Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会创建配套的MeesageQueue.

  (2)有了Looper. 创建Handler子类的实例,重写handleMeesage()方法,该方法负责处理来自其他线程的消息。

  (3)调用Looer的loop()方法来启动Looper.

<5>例子:

public class MainActivity extends ActionBarActivity{
     public Handler mUiHandler;

     class CalcThread extends Thread{
         public Handler mCalcHandler;
         
         public void run(){
            Looper.prepare()
            mCalcHandler = new Handler(){
               public void handleMessage(Message msg){
                 super.handleMeesage(msg);
                 //在新线程这里处理具体的操作,处理完成后可以通过Handler的sendMessage()发送消息
                 if(msg.what == 0x123){
                    ......
                    mUIHandler.sendMessage(...);
                 } 
               }
            };
            Looper.loop();
         }
     }
     
     public void onCreate(Bundle savedInstanceState){
         .....
         //调用CalcThread线程中的mCalcHandler发送消息
         mCalcThread.mCalcHandler.sendMessage(msg);
          
         mUiHandler = new Handler(){
             public void handleMeesage(Meesage msg){
                 类似处理
             }
         };
<pre name="code" class="java">         mCalcThread = new CalcThread();
         mCalcThread.start();



}


}



总结:可以看出来两个线程,相互

调用了对方的Handler对象实现了消息的发送。并且在自己的线程之内, 实现了自己的Handler对象的handleMessage()函数,来处理发送来的消息。另外一个注意的就是新线程,创建的looper对象的问题。