2015/04/28 EventBus初步

问题场景:
一个Activity,一个IntentService。从Activity中获得一个数据,将这个数据通过Intent发送到IntentService中,在IntentService中进行一个长时间的运算,将计算结果返回到Activity中,并在Activity的一个TextView中进行显示。
例如,在Activity中输入一个数字10,在IntentService中计算第十个质数是什么,然后将结果返回给Activity并在Activity的一个TextView中显示。
分析:
利用PendingIntent作为Activity和IntentService之间数据传递的载体。在Activity启动IntentService的Intent对象中,放入一个PendingIntent(PendingIntent实现了Parcelable接口,所以可以将PendingIntent作为Intent的Extra放入)。然后IntentService在计算完毕后,将计算结果放入一个Intent中,并将这个Intent放入前面那个PendingIntent中,调用PendingIntent的send方法。此时Activity的onActivityResult方法会被回调,通过获得方法参数中的Intent类型参数data,将里面的计算结果取出放入TextView显示即可。
代码实现:

Activity的布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:text="请输入一个数字" />

    <EditText
        android:id="@+id/et_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/textView1"
        android:layout_marginTop="27dp"
        android:hint="输入一个整数..."
        android:ems="10" >

        <requestFocus />
    </EditText>

    <TextView
        android:id="@+id/tv_result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/btn_calculate"
        android:layout_alignParentBottom="true"
        android:layout_alignRight="@+id/et_number"
        android:layout_marginBottom="146dp"
        android:text=""
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <Button
        android:id="@+id/btn_calculate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/et_number"
        android:layout_alignRight="@+id/et_number"
        android:layout_below="@+id/et_number"
        android:layout_marginTop="63dp"
        android:text="Button" />

</RelativeLayout>

Activity源文件(使用了xUtils的注入机制):

public class MainActivity extends Activity {
	/**
	 * 利用xUtils的注入机制为属性赋值
	 */
	@ViewInject(R.id.et_number)
	private EditText etNumber;
	@ViewInject(R.id.btn_calculate)
	private Button btnCalculate;
	@ViewInject(R.id.tv_result)
	private TextView tvResult;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		//使用xUtils的ViewUtils实现注入
		ViewUtils.inject(this);
		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	@OnClick({R.id.btn_calculate})
	public void doClick(View v){
		//获得用户输入的数字,用来计算第n个质数是什么
		String value=etNumber.getText().toString();
		//创建一个Intent对象,来启动IntentServic,在后台完成计算
		Intent intent=new Intent(this,MyIntentService.class);
		//将用户输入的数字传入Intent对象
		intent.putExtra(MyIntentService.PARAM, Integer.parseInt(value));
		//创建一个PendingIntent对象,未来在IntentService完成计算后,要利用该PendingIntent将结果送回
		PendingIntent pi=createPendingResult(MyIntentService.RESULT_CODE, new Intent(), 0);
		//PendingIntent实现了Parcelable接口
		intent.putExtra(MyIntentService.PENDING_RESULT, pi);
		//启动IntentService
		startService(intent);
	}
	
	/**
	 * 当IntentService利用PendingIntent返回结果的时候,该方法会被调用
	 * 返回的PendingIntent中会包含一个添加了运算结果的intent对象
	 * 因此从PendingIntent中的Intent中去获取计算结果
	 */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		//Intent类型的参数data是包裹在PendingIntent中的
		if(resultCode==MyIntentService.RESULT_CODE){
			String result=data.getStringExtra(MyIntentService.RESULT);
			tvResult.setText(result);
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

}
MyIntentService的源代码:

public class MyIntentService extends IntentService {

	public static final String PARAM="prime_to_find";
	public static final String PENDING_RESULT="pending_result";
	public static final String RESULT="result";
	public static final int RESULT_CODE="nth_prime".hashCode();
	public static final int INVALID="invalid".hashCode();

	public MyIntentService() {
		super("MyIntentService");
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		try{
			//从来自Activity的Intent中获得用户输入的数值
			int num=intent.getIntExtra(PARAM, -1);
			//从来自Activity的Intent中获得PendingIntent,计算完毕后要使用它返回结果到Activity
			PendingIntent reply=intent.getParcelableExtra(PENDING_RESULT);
			if(num<2) reply.send(INVALID);
			BigInteger prime=getPrime(num);
			//这个Intent用来保存结果,并将该Intent放入PendingIntent中返回到Activity中
			//未来Activity的onActivityResult方法的第三个参数就是该Intent对象
			Intent resultIntent = new Intent();
			resultIntent.putExtra(RESULT, prime.toString());
			reply.send(this, RESULT_CODE, resultIntent);
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	private BigInteger getPrime(int num) {
		BigInteger b=new BigInteger("2");
		for(int n=0;n<num;n++){
			b=b.nextProbablePrime();
		}
		return b;
	}

}
现在使用EventBus进行改写。使用EventBus的时候需要有这样几个元素:自定义的事件对象,事件的发布者,事件的接收者(订阅者)。这样,当有事件发生时,接收者(订阅者)就可以接收到事件对象。接下来接收者利用事件对象提供的方法来操作事件对象即可。对于接收者来说,需要写两个内容:注册和接收事件对象。对于发布者来说,直接发布事件对象即可。

首先写一个自定义的事件类-MyEvent

public class MyEvent {
	private String myMesssage;

	public MyEvent(String myMesssage) {
		super();
		this.myMesssage = myMesssage;
	}

	public String getMyMesssage() {
		return myMesssage;
	}

	public void setMyMesssage(String myMesssage) {
		this.myMesssage = myMesssage;
	}
	
}

未来,把IntentService的运行结果封装为自定义事件对象的myMesssage属性即可。

使用了EventBus的Activity源代码:

public class MainActivity extends Activity {
	/**
	 * 利用xUtils的注入机制为属性赋值
	 */
	@ViewInject(R.id.et_number)
	private EditText etNumber;
	@ViewInject(R.id.btn_calculate)
	private Button btnCalculate;
	@ViewInject(R.id.tv_result)
	private TextView tvResult;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		//使用xUtils的ViewUtils实现注入
		ViewUtils.inject(this);
		//将该Activity注册为事件的接收者
		EventBus.getDefault().register(this);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	@OnClick({R.id.btn_calculate})
	public void doClick(View v){
		//获得用户输入的数字,用来计算第n个质数是什么
		String value=etNumber.getText().toString();
		//创建一个Intent对象,来启动IntentServic,在后台完成计算
		Intent intent=new Intent(this,MyIntentService.class);
		//将用户输入的数字传入Intent对象
		intent.putExtra(MyIntentService.PARAM, Integer.parseInt(value));
		//启动IntentService
		startService(intent);
	}
	/**
	 * 必须写这个方法作为接收者的一部分。这样当有发布者发布事件对象的时候,该方法会被回调
	 * @param event 接收发布者发布的事件对象
	 */
	public void onEventMainThread(MyEvent event){
		String msg=event.getMyMesssage();
		tvResult.setText(msg);

	}
	/**
	 * 在销毁Activity的时候,必须从EventBus中注销掉该接收者
	 */
	@Override
	protected void onDestroy() {
		EventBus.getDefault().unregister(this);
		super.onDestroy();
	}
}

可以看到,这里完全不需要PendingIntent,因此也不需要onActivityResult方法了。此时数据的传递完全依靠事件机制来完成

MyIntentService的源代码:

public class MyIntentService extends IntentService {

	public static final String PARAM="prime_to_find";
	public static final String PENDING_RESULT="pending_result";
	public static final String RESULT="result";
	public static final int RESULT_CODE="nth_prime".hashCode();
	public static final int INVALID="invalid".hashCode();

	public MyIntentService() {
		super("MyIntentService");
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		try{
			//从来自Activity的Intent中获得用户输入的数值
			int num=intent.getIntExtra(PARAM, -1);
			BigInteger prime=getPrime(num);
			//IntentService是事件对象的发布者,将计算结果封装到事件对象中
			EventBus.getDefault().post(new MyEvent(prime.toString()));
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	private BigInteger getPrime(int num) {
		BigInteger b=new BigInteger("2");
		for(int n=0;n<num;n++){
			b=b.nextProbablePrime();
		}
		return b;
	}

}

可以看到,MyIntentService的代码更加的简洁,获得Activity传递过来的用户输入内容,将计算结果封装到事件对象中,并且发布事件即可。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值