1.如何在一个应用程序中定义多个Activity
1)定义一个类,继承Activity
2)在该类中,复写Activity中的onCreate方法
3)在AndroidManifest.xml文件中注册该Activity
//例子中在AndroidManifest.xml中注册了SecondActivity
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.activity03"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.activity03.MainActivity"
android:label="@string/app_name" >
</activity>
<activity
android:name="com.example.activity03.SecondActivity"
android:label="SecondActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
2.启动一个Activity的方法
1)生成一个意图对象(intent)
2)调用setClass方法设置所要启动的Activity
3)调用startActivity方法启动Activity
public class MainActivity extends Activity {
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.button);
button.setOnClickListener(new ButtonListener());
}
class ButtonListener implements OnClickListener{
@Override
public void onClick(View v) {
Intent intent = new Intent();
//setClass函数的第一个参数是一个Context对象
//Context是一个类,Activity是Context类的子类,也就是说Activity对象可以向上转型为Context对象
//setClass函数的第二个参数是一个Class对象,在当前场景下,应该传入启动的Activity的class对象
intent.setClass(MainActivity.this, SecondActivity.class);
startActivity(intent);
}
}
}
3.Android中的back stack(后退栈)
作用:先进后出,只显示栈顶的Activity.当点击后退按钮时,栈顶的Activity移除.用于记录Activity启动的顺序
###Activity生命周期二&三###
###pic1###
1.Activity的生命周期函数
onCreate:在Activity对象被第一次创建时调用
onStart:当Activity变得可见时调用该函数
onResume:当Activity开始准备与用户交互时调用该方法
onPause:当系统即将启动另外一个Activity之前调用该方法
onStop:当前Activity变得不可见时调用该方法
onDestroy:当前Activity被销毁之前将会调用该方法
onRestart:当一个Activity再次启动之前将会调用该方法
2.Activity对象的状态
1)Resumed:Activity对象处于运行状态
2)Paused:另一个Activity位于前端,但是本Activity还可见
3)Stopped:另一个Activity位于前端,完全遮挡本Activity
3.成对的生命周期函数
onCreate Vs. onDestory
onStart Vs. onStop
onResume Vs. onPause
###Intent###
1.Intent对象的基本概念
Intent是Android应用程序组件之一
Intent对象在Android系统当中表示一种意图
Intent当中最重要的内容是Action与data
2.使用Intent在Activity之间传递数据的方法
1)在Activity之间可以通过Intent对象传递数据
2)使用putExtra()系列方法向Intent对象当中存储数据
class ButtonListener implements OnClickListener {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, OtherActivity.class);
//使用putExtra()系列方法向Intent对象当中存储数据
intent.putExtra("com.example.s02e04_intent.Age", 20);
startActivity(intent);
}
}
3)使用getXXXExtra()系列方法从Intent对象中取出数据
public class OtherActivity extends Activity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.other);
//getIntent获取intent的实例
Intent intent = getIntent();
//使用getXXXExtra()系列方法从Intent对象中取出数据
int age = intent.getIntExtra("com.example.s02e04_intent.Age", 10);
textView =(TextView)findViewById(R.id.textView);
textView.setText(age+" ");
}
}
###线程###
1.MainThread
MainThread即UI线程,UI界面相关的,都显示在MainThread中
主线程之外,原则上不能修改UI,但可以修改Progress bar
主线程通常用于接受用户的输入,将运算的结果发聩给用户
2.Worker Thread
其他的线程叫Worker Thread
对于一些可能阻塞的操作,必须放置在Worker Thread中
###Handler、Looper和MessageQueue的基本原理###
解决线程间通讯
1)Handler负责把消息对象加入到消息队列(MessageQueue)中
2)Looper不停的从消息队列中向外取出消息对象,如果消息队列中没消息,Looper就处于等待状态
3)Looper将找到与消息对象对应的Handler对象
4)Looper调用Handle的handleMessage方法,处理消息对象
public class MainActivity extends Activity {
private Button button;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.buttonId);
button.setOnClickListener(new ButtonListener());
handler = new FirstHandler();
}
class ButtonListener implements OnClickListener{
@Override
public void onClick(View v) {
//当用户点击按钮时,我们创建一个消息对象,并使用Handler发送该对象
Message msg = handler.obtainMessage(); //每个消息对象都有对应的Handler对象
msg.what = 2;
handler.sendMessage(msg);
//上面一行代码将消息对象放置到消息队列当中
//1.Looper将会从消息队列中将消息对象取出
//2.Looper将找到与消息对象对应的Handler对象
//3.Looper将会调用handler对象的handleMessage(Message msg)方法,用于处理消息对象
}
}
class FirstHandler extends Handler{
@Override
public void handleMessage(Message msg) {
int what = msg.what;
System.out.println("what:" + what);
}
}
###通过Handle实现线程间通讯###
1.workerTread发送消息到主线程
在主线程当中实现Handler的handleMessage()方法
在Worker Thread当中通过Handler发送消息
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.buttonId);
button.setOnClickListener(new ButtonListener());
textView = (TextView)findViewById(R.id.textViewId);
handler = new MyHandler();
}
class MyHandler extends Handler{
@Override
public void handleMessage(Message msg) {
System.out.println("handleMessage======>" + Thread.currentThread().getName());
String s = (String)msg.obj;
textView.setText(s);
}
}
class NetWorkThread extends Thread{
@Override
public void run() {
System.out.println("network------->" + Thread.currentThread().getName());
//模拟访问网络,所以说当线程运行时,首先休眠2s
try {
Thread.sleep(2*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//变量s的值,模拟从网路中获取的值
String s = "从网络中获取的数据";
//textView.setText(s); 错误的,因为只有主线程才能改UI
Message msg = handler.obtainMessage();
msg.obj = s;
//sendMessage()方法,无论是在主线程中发送还是worker thread中发送,都是可以的
handler.sendMessage(msg);
}
}
class ButtonListener implements OnClickListener{
@Override
public void onClick(View v) {
Thread t = new NetWorkThread();
t.start();
}
}
2.主线程发送消息到workerTread
Looper->MessageQueue->Thread->Handler一一对应
1)准备Looper对象
2)在WorkerThread中生成一个Handler对象
3)调用Looper的loop方法之后,loop对象将不断的从消息队列中取出消息对象,然后调用handler的handleMessage()方法,处理该消息对象
/***
*
* 在WorkerThread中生成handler,然后在MainThread中使用这个Handler发送消息,通过消息队列,然后由Looper对象
把消息对象取出来,然后在把这个消息对象传递给handle的handleMessage()方法来处理(处于workerThread中)
*
*/
public class MainActivity extends Activity {
private Button button;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.buttonId);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Message msg = handler.obtainMessage();
handler.sendMessage(msg);
}
});
WorkerThread wt = new WorkerThread();
wt.start();
}
class WorkerThread extends Thread{
@Override
public void run() {
//1.准备Looper对象
Looper.prepare();
//2.在WorkerThread中生成一个Handler对象
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
System.out.println("收到了消息对象");
}
};
//3.调用Looper的loop方法之后,loop对象将不断的从消息队列中取出消息对象,然后调用handler的handleMessage()方法,处理该消息对象
//如果消息队列为空,则该线程阻塞
Looper.loop();
}
}
###Handler、Looper和MessageQueue的源代码基本关系###
1.ThreadLocal:线程本地变量
执行ThreadLocal对象的set(Object)方法,将会存入一个以当前线程为键的键值对
执行ThreadLocal对象的get()方法,将会根据当前线程对象为键,取出与之对应的值
通过静态变量ThreadLocal,使Looper,MessageQueue,Thread和Handler一一对应
ThreadLocal用于存放键值对(键是当前线程对象,值是Looper对象)
2.Handler的post(Runnabler)方法
1)如何能够把一个Runnable对象放置在消息队列中;实际上是生成了一个Message对象,并将r赋值给Message对象的callback属性,然后再将Message对象放置在消息队列中
2)Looper取出携带r的Message对象之后,干了些什么;取出Message对象后调用disPatchMessage方法,然后判断Message的callback属性是否为空,此时callback属性有值,所以执行handleCallback(Message msg),该方法中执行了msg.callback.run()
//private static Message getPostMessage(Runnable r)
//1.该方法完成了两个操作,第一生成了一个Message对象;第二,将r对象赋值给Message对象的callback属性
//第一个问题:如何能够把一个Runnable对象放置在消息队列中;实际上是生成了一个Message对象,
//并将r赋值给Message对象的callback属性,然后再将Message对象放置在消息队列中
//第二个问题:Looper取出携带r的Message对象之后,干了些什么;取出Message对象后调用disPatchMessage方法,然后判断Message的callback属性是否为空
//此时callback属性有值,所以执行handleCallback(Message msg),该方法中执行了msg.callback.run()
public class MainActivity extends Activity {
private Button button;
private Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.buttonId);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
TestThread tt = new TestThread();
tt.start();
}
});
}
class TestThread extends Thread{
@Override
public void run() {
//从网络上取回数据
Runnable r = new Runnable(){
@Override
public void run() {
//这里可以写上更新UI的代码
String currentThreadName = Thread.currentThread().getName();
System.out.println("当前线程的名称为:" + currentThreadName);
}
};
//post(r)将r对象放置在消息队列中,Looper对象(主线程)从消息队列中取出r对象
//我们猜测:取出r对象之后
//1.Thread t = new Thread(r);
//2.t.start()
//根据测试记过可以看出,该思路是错误的
//我们的问题是Looper取出r对象之后,干了些什么
//1)第一生成了一个Message对象;将r对象赋值给Message对象的callback属性
//2)第二将Message对象放到了消息队列中
handler.post(r);
}
}
###Http协议###
1.HttpClient使用步骤:
1)生成代表客户端的HttpClient对象
2)生成代表请求的HttpGet对象
3)发送请求,获得服务器返回的HttpResponse对象
4)检查响应状态是否正常
5)获取响应对象当中的数据
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.buttonId);
button.setOnClickListener(new ButtonListener());
}
class ButtonListener implements OnClickListener{
@Override
public void onClick(View v) {
//原则:主线程中不能访问网络
NetworkThread nt = new NetworkThread();
nt.start();
}
}
class NetworkThread extends Thread{
@Override
public void run() {
//创建HttpClient
HttpClient httpClient = new DefaultHttpClient();
//创建代表请求的对象,参数是访问的服务器地址
//http://www.marschen.com/data1.html
HttpGet httpGet = new HttpGet("http://www.marschen.com/data1.html");
//执行请求,获取服务器返还的响应对象
try {
HttpResponse resp = httpClient.execute(httpGet);
//检查响应的状态是否正常,检查状态码是否等于200
int code = resp.getStatusLine().getStatusCode();
if(code == 200){
//从响应对象中取出数据
HttpEntity entity = resp.getEntity();
InputStream in = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = reader.readLine();
Log.d("HTTP", "从服务器取得的数据为:" + line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.HTTP请求头
1)HTTP请求内容分析
Host www.marschen.com 本次请求访问主机地址
Cache-Control no-cache 设置网页缓存的使用方法
Pragma no-cache
Accept image/jpeg, .... 浏览器可以接受的数据类型
User-Agent Mozilla/4.0 主要表示客户端类型
Accept-Encoding gzip, deflate 浏览器能够解码的数据编码方式
Accept-Language en-US 浏览器期望的接受的语言种类
2)HTTP响应内容分析
Content-Encoding 返回数据的压缩格式
Content-Length 返回数据量的大小
Content-Type 返回数据的类型
Last-Modified 资源最后一次修改时间
Date 返回数据的时间
Server 服务器类型
3)HTTP请求头与响应头的读取
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.buttonId);
button.setOnClickListener(new ButtonListener());
}
class ButtonListener implements OnClickListener{
@Override
public void onClick(View v) {
//原则:主线程中不能访问网络
NetworkThread nt = new NetworkThread();
nt.start();
}
}
class NetworkThread extends Thread{
@Override
public void run() {
//创建HttpClient
HttpClient httpClient = new DefaultHttpClient();
//创建代表请求的对象,参数是访问的服务器地址
//http://www.marschen.com/data1.html
HttpGet httpGet = new HttpGet("http://www.marschen.com/data1.html");
httpGet.addHeader("Accept-Language", "zh-CN,zh;q=0.8");
Header [] reqHeaders = httpGet.getAllHeaders();
for(int i=0; i<reqHeaders.length; i++){
String name = reqHeaders[i].getName();
String value = reqHeaders[i].getValue();
Log.d("Http01","request header--Name:" + name + ",value" + value);
}
//执行请求,获取服务器返还的响应对象
try {
HttpResponse resp = httpClient.execute(httpGet);
Header[] respHeaders = resp.getAllHeaders();
for(int i=0; i<respHeaders.length; i++){
String name = respHeaders[i].getName();
String value = respHeaders[i].getValue();
Log.d("Http01","response header--Name:" + name + ",value" + value);
}
//检查响应的状态是否正常,检查状态码是否等于200
int code = resp.getStatusLine().getStatusCode();
if(code == 200){
//从响应对象中取出数据
HttpEntity entity = resp.getEntity();
InputStream in = entity.getContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = reader.readLine();
Log.d("HTTP", "从服务器取得的数据为:" + line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.Get与Post方法
1)GET--类似明信片
从服务器取回数据
使用GET方法向服务器提交的数据量小,通常不超过2K
GET请求是将所要提交的数据附在URL之后
2)POST--类似信
向服务器提交数据
使用POST向服务器提交的数据量通常没有限制
POST请求是将提交的数据放置在请求的请求体中
3)POST提交数据的步骤
a.构造请求对象
b.将需要传递给服务器端的数据放置在键值对对象当中
c.将准备好的键值对放置在List当中;
d.生成代表请求体的对象;
e.将存有请求键值对的List对象放置在请求题对象当中;
f.将请求体对象放置到请求对象当中;
g.发送请求对象
public class MainActivity extends ActionBarActivity {
private EditText nameText;
private EditText pwdText;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nameText = (EditText) findViewById(R.id.nameText);
pwdText = (EditText) findViewById(R.id.pwdText);
button = (Button) findViewById(R.id.submitButton);
button.setOnClickListener(new ButtonListener());
}
class ButtonListener implements OnClickListener {
@Override
public void onClick(View v) {
String name = nameText.getText().toString();
String pwd = pwdText.getText().toString();
//使用GET方法向服务器发送请求
// GetThread gt = new GetThread(name, pwd);
// gt.start();
//使用POST方法向服务器发送请求
PostThread pt = new PostThread(name, pwd);
pt.start();
}
}
//该线程使用POST方法向服务器发送请求
class PostThread extends Thread {
String name;
String pwd;
public PostThread(String name, String pwd) {
this.name = name;
this.pwd = pwd;
}
@Override
public void run() {
HttpClient httpClient = new DefaultHttpClient();
String url = "http://192.168.1.103:8080/s02e14.jsp";
//生成使用POST方法的请求对象
HttpPost httpPost = new HttpPost(url);
//NameValuePair对象代表了一个需要发往服务器的键值对
NameValuePair pair1 = new BasicNameValuePair("name", name);
NameValuePair pair2 = new BasicNameValuePair("password", pwd);
//将准备好的键值对对象放置在一个List当中
ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>();
pairs.add(pair1);
pairs.add(pair2);
try {
//创建代表请求体的对象
HttpEntity requestEntity = new UrlEncodedFormEntity(pairs);
//将请求体放置在请求对象当中
httpPost.setEntity(requestEntity);
//执行请求对象
try {
HttpResponse response = httpClient.execute(httpPost);
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
BufferedReader reader = new BufferedReader(
new InputStreamReader(entity.getContent()));
String result = reader.readLine();
Log.d("HTTP", "POST:" + result);
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class GetThread extends Thread {
String name;
String pwd;
public GetThread(String name, String pwd) {
this.name = name;
this.pwd = pwd;
}
@Override
public void run() {
HttpClient httpClient = new DefaultHttpClient();
String url = "http://192.168.1.103:8080/s02e14.jsp?name=" + name+ "&password=" + pwd;
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse response = httpClient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
BufferedReader reader = new BufferedReader(
new InputStreamReader(entity.getContent()));
String result = reader.readLine();
Log.d("HTTP", "GET:" + result);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}