小猪的Android入门之路 Day 9 part 2

小猪的Android入门之路 Day 9 part 2

Android四大组件之——AIDL实现跨进程通信

——转账请注明出处:coder-pig

本节引言:

在上一part中我们对Service进行了简单的学习:

什么是Service,Service的生命周期,StartService和BindService的区别以及使用

IntentService来解决Service的异步问题;

而在今天的这一Part中将会研究另一个东西:IPC,安卓给我们提供了AIDL Service

来完成进程间的数据交换!好了,开始本节的内容吧!

本节学习路线图:

正文:

看这篇博文的人,不知道你能不能坚持地看完本篇内容,为了照顾你们,直接把总结用法放到本文的开头!

AIDL简介:

开头我们说的IPC,全名叫做跨进程通信(interprocess communication),因为在Android系统中,

个个应用程序都运行在自己的进程中,进程之间一般是无法直接进行数据交换的,而为了实现跨进程

间的通信,Android给我们提供了AIDL技术,AIDL(Android Interface Definition Language)是一种

接口语言,语法十分的简单,这种接口语言并不是真正的编程语言,只是定义两个进程间的通信接口而已!

而生成符合通信协议的Java代码则是由Android
SDK的platform-tools下的aidl.exe工具自动地在gen

目录下生成一个对应的Xxx.java的接口,在该接口中包含一个Stub的内部类,在该类中实现了IBinder接口

与自定义的通信接口,这个类将会作为远程Service的回调类——实现了IBinder接口,所以可作为Service

的onBind( )方法的返回值!

使用AIDL完成两个进程之间的简单通信

一.建立作为服务端的工程:

step 1:创建IPerson.aidl文件,不要直接new file然后建立哦!这样的话是打不开文件,从而不能编写代码哦!

①直接新建一个txt文件,编写好后保存为.aidl格式,然后复制到对应路径下

②因为aidl和接口类似,所以直接new interface,编写好内容后,来到对应java文件所在目录下修改文件后缀名;

然后点击刷新即可,另外编写ADIL文件时有以下注意事项:

1.接口名词需要与aidl文件名相同

2.接口和方法前面不要加访问权限修饰符:public ,private,protected等,也不能用static final!

3.AIDL默认支持的类型包括Java基本类型,String,List,Map,CharSequence,除此之外的其他类型都需要import

声明,对于使用自定义类型作为参数或者返回值,自定义类型需要实现Parcelable接口,详情请看后面的传递复杂数据类型

4.自定义类型和AIDL生成的其它接口类型在aidl描述文件中,应该显式import,即便在该类和定义的包在同一个包中。

编写IPerson.aidl文件内容如下:

package com.example.aidl;

interface IPerson {
	String queryPerson(int num);
}

此时只要我们按下刷新或者不用,就可以看到gen目录下生成了一个接口对应的实现:

我们可以打开IPerson.java看看里面的代码

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: E:\\Eandroid_code\\AIDL_Service\\src\\com\\example\\aidl\\IPerson.aidl
 */
package com.example.aidl;
public interface IPerson extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.example.aidl.IPerson
{
private static final java.lang.String DESCRIPTOR = "com.example.aidl.IPerson";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
 * Cast an IBinder object into an com.example.aidl.IPerson interface,
 * generating a proxy if needed.
 */
public static com.example.aidl.IPerson asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof com.example.aidl.IPerson))) {
return ((com.example.aidl.IPerson)iin);
}
return new com.example.aidl.IPerson.Stub.Proxy(obj);
}
@Override public android.os.IBinder asBinder()
{
return this;
}
@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
{
switch (code)
{
case INTERFACE_TRANSACTION:
{
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_queryPerson:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
java.lang.String _result = this.queryPerson(_arg0);
reply.writeNoException();
reply.writeString(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
private static class Proxy implements com.example.aidl.IPerson
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
@Override public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
@Override public java.lang.String queryPerson(int num) throws android.os.RemoteException
{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
java.lang.String _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(num);
mRemote.transact(Stub.TRANSACTION_queryPerson, _data, _reply, 0);
_reply.readException();
_result = _reply.readString();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_queryPerson = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public java.lang.String queryPerson(int num) throws android.os.RemoteException;
}

我们关注的只是asInterface(IBinder)和我们定义的接口中的queryPerson()方法!

该方法会把IBinder类型的对象转换成IPerson类型的,必要时生成一个代理对象返回结果!

当然,你也可以选择不看,因为我们完全可以跳过这里去进行下一步,这里只是了解下而已!

step 2:自定义我们的Service类,完成下述操作:

1)继承Service类,同时也自定义了一个PersonQueryBinder类用来继承IPerson.Stub类

就是实现了IPerson接口和IBinder接口

2)实例化自定义的Stub类,并重写Service的onBind方法,返回一个binder对象!

AidlService.java

package com.example.aidl_service;

import com.example.aidl.IPerson.Stub;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class AidlService extends Service {

	private IBinder binder = new PersonQueryBinder();
	private String[] names = {"小涛","刘老师","蓝翔","挖掘机"};

	@Override
	public IBinder onBind(Intent intent) {
		return binder;
	}

	private String query(int num)
	{
		if(num > 0 && num < 5){
			return names[num - 1];
		}
		return null;
	}

	private final class PersonQueryBinder extends Stub{
		@Override
		public String queryPerson(int num) throws RemoteException {
			return query(num);
		}
	}

}

step 3:在AndroidManifest.xml文件中注册Service

        <service android:name=".AidlService">
            <intent-filter>
        		<action android:name="android.intent.action.AIDLService" />
    			<category android:name="android.intent.category.DEFAULT" />
    		</intent-filter>
        </service>

这里并没有提供Activity界面,当着没关系,该应用提供的Service可以供其他app来调用!

二.建立作为客户端的工程:

首先需要把我们把服务端创建的IPerson.aidl文件复制过来,然后

我们直接在MainActvivity中完成,和绑定本地Service的操作类似:

1)自定义PersonConnection类实现ServiceConnection接口

2)以PersonConnection对象作为参数,调用bindService绑定远程Service

bindService(service, conn, BIND_AUTO_CREATE);

ps:第三个参数是设置如果服务没有启动的话,自动创建

3)和本地Service不同,绑定远程Service的ServiceConnection并不能直接获取Service的onBind(
)方法

返回的IBinder对象,只能返回onBind( )方法所返回的代理对象,需要做如下处理:

iPerson = IPerson.Stub.asInterface(service);

再接着完成初始化,以及按钮事件等就可以了

MainActvitiy.java

package com.jay.example.aidl_client;

import com.example.aidl.IPerson;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

	private EditText editnum;
	private Button btnquery;
	private TextView txtshow;
	private IPerson iPerson;
	private PersonConnection conn = new PersonConnection();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		editnum = (EditText) findViewById(R.id.editnum);
		btnquery = (Button) findViewById(R.id.btnquery);
		txtshow = (TextView) findViewById(R.id.txtshow);

		Intent service = new Intent("android.intent.action.AIDLService");
		bindService(service, conn, BIND_AUTO_CREATE);

		btnquery.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				String number = editnum.getText().toString();
				int num = Integer.valueOf(number);
				try {
					txtshow.setText(iPerson.queryPerson(num));
				} catch (RemoteException e) {
					e.printStackTrace();
				}
			}
		});

	}

	@Override
	protected void onDestroy() {
		unbindService(conn);
		super.onDestroy();
	}

	private final class PersonConnection implements ServiceConnection {
		public void onServiceConnected(ComponentName name, IBinder service) {
			iPerson = IPerson.Stub.asInterface(service);
		}
		public void onServiceDisconnected(ComponentName name) {
			iPerson = null;
		}
	}

}

然后先启动我们的AIDL_Service,再接着启动AIDL_Cilent,输入要查询的姓名序号,即可知道对应姓名!

当然也可以直接启动AIDL_Client,也可以获得相同的结果!

效果图:

好了,对于AIDLService的简单实用示例就到这里,后续如果有更好的例子会再给出!

传递复杂数据的AIDL Service

上面的简单示例中,客户端向服务端发送了一个int类型的参数,然后服务端返回一个String类型的参数,看似已经

基本满足我们的需求了,但是实际情况下,我们还需要考虑向客户端传递复杂数据类型的情况!那么下面就来讲

解下如何向服务端传递复杂数据类型的问题!

1.先要了解的是Parcelable接口,对于自定义类型,Android规定调用远程Service的参数与返回值都必须实现

Parcelable接口,该接口告诉Android运行时在封送(marshalling)和解封送(unmarshalling)过程中如何序列化

与反序列化对象,这个时候你或许会有疑惑,为什么不直接用Java提供的Serializable接口呢?这是因为Android

团队觉得Java序列化太慢,难以满足Android的进程间的通信需求,所以他们构建了Parcelable方案!

---->也就是自定义的对象要实现Parcelable接口!实现接口要实现下述方法

※实现Paecelable接口意味着要实现writeToParcel和readFromPacel方法;

写入方法将对象写入到包裹(parcel)中,而读取方法则从包裹中读取对象,请注意,写入属性顺序需与读取顺序相同

※需要在该类中添加一个名为CREATOR的static final属性,该属性需要实现android.os.Parcelable.Creator<T>接口

里面的两个方法

createFromParcel(Parcel source)方法:实现从source创建出JavaBean实例的功能

newArray(int size):创建一个类型为T,长度为size的数组,只有一个简单的return new T[size]; (这里的T是Person类)

※describeContents():这个我也不知道是拿来干嘛的,直接返回0即可!不用理他

2.非原始类型中,除了String和CharSequence以外,其余均需要一个方向指示符。方向指示符包括

in、out、和inout。in表示由客户端设置,out表示由服务端设置,inout表示客户端和服务端都设置了该值。

代码实例:

这里我们自定义两种对象类型:Person与Salary,Person作为调用远程的Service的参数,Salary作为返回值!

那么首先要做的就是创建Person与Salary类,同时需要实现Parcelable接口 

一.服务端的编写

step 1.先建立Person.aidl和Salary.aidl的文件,因为这两个需要实现Parcelable接口,就下面简单的一句!

Person.aidl:     parcelable Person; 

Salary.aidl:     parcelable Salary;  

step 2.分别建立Person类与Salary类,都需要实现Parcelable接口.重写对应的方法!

另外因为我们后面是根据Person对象来获取Map集合中的数据,所以Person.java中我们重写了hashcode和equals

的方法;而Salary类则不需要!

Person.java:

package com.jay.example.aidl;

import android.os.Parcel;
import android.os.Parcelable;

public class Person implements Parcelable{
	private Integer id;
	private String name;

	public Person(){}

	public Person(Integer id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	//实现Parcelable必须实现的方法,不知道拿来干嘛的,直接返回0就行了
	@Override
	public int describeContents() {
		return 0;
	}

	//写入数据到Parcel中的方法
	@Override
	public void writeToParcel(Parcel dest, int flags) {
		//把对象所包含的数据写入到parcel中
		dest.writeInt(id);
		dest.writeString(name);
	}

	//必须提供一个名为CREATOR的static final属性 该属性需要实现
	//android.os.Parcelable.Creator<T>接口
	 public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {

		//从Parcel中读取数据,返回Person对象
		@Override
		public Person createFromParcel(Parcel source) {
			return new Person(source.readInt(),source.readString());
		}

		@Override
		public Person[] newArray(int size) {
			return new Person[size];
		}

	 };

	//因为我们集合取出元素的时候是根据Person对象来取得,所以比较麻烦,
	//需要我们重写hashCode()和equals()方法
		@Override
		public int hashCode()
		{
			final int prime = 31;
			int result = 1;
			result = prime * result + ((name == null) ? 0 : name.hashCode());
			return result;
		}
		@Override
		public boolean equals(Object obj)
		{
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Person other = (Person) obj;
			if (name == null)
			{
				if (other.name != null)
					return false;
			}
			else if (!name.equals(other.name))
				return false;
			return true;
		}

}

接着是Salary类了,照葫芦画瓢,都是类似的:

Salary.java:

package com.jay.example.aidl;

import android.os.Parcel;
import android.os.Parcelable;

public class Salary implements Parcelable{
	private String type;
	private Integer salary;

	public Salary(){}

	public Salary(String type, Integer salary) {
		super();
		this.type = type;
		this.salary = salary;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public Integer getSalary() {
		return salary;
	}

	public void setSalary(Integer salary) {
		this.salary = salary;
	}

	//实现Parcelable必须实现的方法,不知道拿来干嘛的,直接返回0就行了
	@Override
	public int describeContents() {
		return 0;
	}

	//写入数据到Parcel中的方法
	@Override
	public void writeToParcel(Parcel dest, int flags) {
		//把对象所包含的数据写入到parcel中
		dest.writeString(type);
		dest.writeInt(salary);
	}

	//必须提供一个名为CREATOR的static final属性 该属性需要实现
	//android.os.Parcelable.Creator<T>接口
	 public static final Parcelable.Creator<Salary> CREATOR = new Parcelable.Creator<Salary>() {

		//从Parcel中读取数据,返回Person对象
		@Override
		public Salary createFromParcel(Parcel source) {
			return new Salary(source.readString(),source.readInt());
		}

		@Override
		public Salary[] newArray(int size) {
			return new Salary[size];
		}

	 };

	public String toString()
	{
		return "工作:"+type+"    薪水"+salary;
	};

}

嗯呢,完成上述四个文件后,接着就搞个ISalary.aidl了,我们在里面只写一个简单的获取工资信息的方法

ISalary.aidl:

package com.jay.example.aidl;

import com.jay.example.aidl.Salary;
import com.jay.example.aidl.Person;
interface ISalary
{
	//定义一个Person对象作为传入参数
	//接口中定义方法时,需要制定新参的传递模式,这里是传入,所以前面有一个in
	Salary getMsg(in Person owner);
}      

ps:这里可以记得如果使用的是自定义的数据类型的话,需要import哦!!!切记!!!

接着就到服务端的核心Service的编写了!

定义一个SalaryBinder类继承Stub,从而实现ISalary和IBinder接口;定义一个存储信息的Map集合!

重新onBind方法,返回SalaryBinder类的对象实例!

AidlService.java

package com.jay.example.aidl_complexservice;

import java.util.HashMap;
import java.util.Map;

import com.jay.example.aidl.ISalary.Stub;
import com.jay.example.aidl.Person;
import com.jay.example.aidl.Salary;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class AidlService extends Service {

	private SalaryBinder salaryBinder;
	private static Map<Person,Salary> ss = new HashMap<Person, Salary>();
	//初始化Map集合,这里在静态代码块中进行初始化,当然你可也以在构造方法中完成初始化
	static
	{
		ss.put(new Person(1, "Jay"), new Salary("码农", 2000));
		ss.put(new Person(2, "GEM"), new Salary("歌手", 20000));
		ss.put(new Person(3, "XM"), new Salary("学生", 20));
		ss.put(new Person(4, "MrWang"), new Salary("老师", 2000));
	}

	@Override
	public void onCreate() {
		super.onCreate();
		salaryBinder = new SalaryBinder();
	}

	@Override
	public IBinder onBind(Intent intent) {
		return salaryBinder;
	}

	//同样是继承Stub,即同时实现ISalary接口和IBinder接口
	public class SalaryBinder extends Stub
	{

		@Override
		public Salary getMsg(Person owner) throws RemoteException {
			return ss.get(owner);
		}

	}

	@Override
	public void onDestroy() {
		System.out.println("服务结束!");
		super.onDestroy();
	}

}

最后别忘了需要在AndroidManifest.xml文件中注册Service哦!

 <service android:name=".AidlService">
            <intent-filter>
        		<action android:name="android.intent.action.AIDLService" />
    			<category android:name="android.intent.category.DEFAULT" />
    		</intent-filter>
        </service>

二.客户端的编写:

1.先把服务端的AIDL的文件直接拷贝过来,拷贝后的目录如下:

2.编写简单的布局,再接着就是核心MainActvitiy的实现了

定义一个ServciceConnection对象,重写对应方法,和前面的普通数据的类似

再接着在bindService,然后再Button的点击事件中获取Salary对象并显示出来!

MainActivity.java

package com.jay.example.aidl_complexclient;

import com.jay.example.aidl.ISalary;
import com.jay.example.aidl.Person;
import com.jay.example.aidl.Salary;

import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

	private ISalary salaryService;
	private Button btnquery;
	private EditText editname;
	private TextView textshow;
	private ServiceConnection conn = new ServiceConnection() {

		@Override
		public void onServiceDisconnected(ComponentName name) {
			salaryService = null;
		}

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			//返回的是代理对象,要调用这个方法哦!
			salaryService = ISalary.Stub.asInterface(service);
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		btnquery = (Button) findViewById(R.id.btnquery);
		editname = (EditText) findViewById(R.id.editname);
		textshow = (TextView) findViewById(R.id.textshow);

		Intent it = new Intent();
		it.setAction("com.jay.aidl.AIDL_SERVICE");
		bindService(it, conn, Service.BIND_AUTO_CREATE);

		btnquery.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				try
				{
					String name = editname.getText().toString();
					Salary salary = salaryService.getMsg(new Person(1,name));
					textshow.setText(name + salary.toString());
				}catch(RemoteException e){e.printStackTrace();}
			}
		});

	}
	@Override
	protected void onDestroy() {
		super.onDestroy();
		this.unbindService(conn);
	}

}

运行截图:

好了,关于Android中的跨进程IPC的代表AIDL就讲解到这里,如果后续有什么新的知识点会

在进行补偿!谢谢支持!

本节相关代码下载:

1)使用AIDL完成进程间的简单通信:点击下载

2)传递复杂数据的AIDL Service的实现:点击下载

时间: 2024-10-11 15:24:03

小猪的Android入门之路 Day 9 part 2的相关文章

小猪的Android入门之路 Day 8 part 2

小猪的Android入门之路 Day 8 part 2 Android网络编程浅析--Android访问网络资源 --转载请注明出处:coder-pig 本节引言: 在part 1中我们学习了网络交互中用得较多的xml文件的相关概念,以及在Android中常用的 解析XML三种不同形式,分别SAX,DOM,Pull三种不同的解析方式;而在part 2中我们将会 讲解我们的应用如何去获取网络上的资源,分别是图片,HTML代码,XML代码和JSON数据; 好了,废话就这么多,开始本节的课程吧!从这p

小猪的Android入门之路 Day 8 part 4

小猪的Android入门之路 Day 8 part 4 Android网络编程浅析--Android网络数据的上传 --转载请注明出处:coder-pig 本节引言: 在part 3中我们已经学习了Android网络数据的下载,难点是多线程断点续传下载; 有下载,当然也有上传啦,本节就来研究下Android中的网络数据的上传! 1.使用GET或者Post方式上传数据给服务器 2.使用开源框架HttpClient上传数据到服务区 3.发送xml数据给服务器 4.通过Http协议上传文件 5.Web

小猪的Android入门之路 Day 4 - part 4

小猪的Android入门之路 Day 4 - part 4 Android事件处理机制之--事件处理机制拾遗 ------------转载请注明出处--coder-pig 本节引言: 在前面三个部分中,对于android的事件处理机制的学习已经学得七七八八了, 基于监听与回调的时间处理机制,以及使用Handler传递信息的机制都已经学了; 在最后这个部分中会对一些小的知识点进行补充,比如触摸事件的两种形式, Configuration类以及异步任务AsyncTask进行讲解,好了,开始本节的课程

小猪的Android入门之路 Day 3 - part 1

小猪的Android入门之路 Day 2 各种UI组件的学习 Part 1 本节引言: 在上一节中,我们初次体验了Android开发的一个流程,开发了一个简单的电话拨号器; 然后又学习了android的六大布局,界面无非是由布局 + 控件构成;布局都学了,剩下的 当然是控件啦,不过Android 所提供的UI组件还是比较丰富的;我们不求掌握他们的全部 用法,只需要了解一些基本的用法,等需要时再查资料就可以了!当然,内容是以android UI 组件实例大全为依托的,因为内容较多,所以需要分成几个

小猪的Android入门之路 Day 7 part 4

小猪的Android入门之路 Day 7 part 4 Android的数据存储与访问之--ContentProvider(内容提供者)                                   ---转载请注明出处:coder-pig 本节引言: 在前面的学习中,我们已经学习了一些存储数据的方式,而这些都是可以共享的,比如文件,我们可以把操作 模式设置为Context.MODE_WORLD_READABLE 或Context.MODE_WORLD_WRITEABLE,其他应用 就可以

小猪的Android入门之路 Day 5 - part 1

小猪的Android入门之路 Day 5 - part 1 基本程序单元:Activity(活动) ------------转载请注明出处--coder-pig 本节引言: 经过前面的学习,我们已经可以开发出一个自定义简单UI界面以及具有简单逻辑业务的App了, 不过都是在一个界面上完成的,而现在大部分的app都是拥有多个界面的,所以我们有必要继续深入地 学习,而这些所谓的界面,窗口,在Android我们把他们叫做Activity(活动),他也是Android四大组件的其中 一个,是基本的程序单

小猪的Android入门之路 Day 4 - part 3

小猪的Android入门之路 Day 4 - part 3 Android事件处理机制之--Handler消息传递机制 ------------转载请注明出处--coder-pig 本节引言: 在前面两个部分中,我们对于android的两种事件处理机制:监听与回调进行了深入的学习; 貌似就学完android的事件处理机制了,其实这两个仅仅是发生了触摸啊之类做出的事件响应; 而今天这一Part要讲的是修改Activity中的UI组件时发生一些信息传递;相信大家都知道,我们只能够 主线程中去修改Ac

小猪的Android入门之路 Day 4 - part 1

小猪的Android入门之路 Day 4 - part 1 Android事件处理机制之--基于监听的事件处理机制 本节引言: 在开始本个章节前,我们先回顾下,现在我们已经知道了android的一些相关背景,一些常用的UI组件, 六大布局,现在的我们已经可以做出一个简单的app界面了,下一步就是逻辑与业务的实现了;在前面 的例子中我们曾经看到过setXXXListener这些东东,这个就是android 的事件处理,而这个方法是基于监听的 Android为我们提供了两套功能强大的事件处理机制:

小猪的Android入门之路 Day 6

小猪的Android入门之路 Day 6 Android应用核心:Intent(意图) -----转载请注明出处:coder-pig 本节引言: 通过前面的学习中,我们都知道可以调用startActivity(intent)或者startActivityForResult(intent) 来启动一个新的Activity了,他们的参数都是Intent类型的实例,那么这个Intent是什么东西呢? 有什么用?还有一个问题,相信细心的朋友都发现AndroidManifest.xml的activity标

小猪的Android入门之路 day 1

小猪的Android入门之路 Day 1 Android相关背景与开发环境的搭建 ------转载请注明出处:coder-pig 本节引言: 随着社会经济的发展,移动互联网的越来越热,手机APP开发显得格外火爆, 作为一名快要毕业的IT屌丝,自然要趟一趟这一浑水啦,当前主流的手机系统 IOS(苹果),Android(安卓),WinPhone(windows);WindPhone貌似没什么崛起的势头; 所以主流的就是前面的两个;作为一名屌丝学生狗,买不起Mac,仅仅有一台双核的破电脑; 仅仅能去搞