Android 开发的几个小问题二

继续整理一下做 Android 开发过程中遇到的一些问题和技巧。

1. 4.0 或以上版本的 Android 不能在主线程中联网

Android 应用程序运行在一个 dalvik 虚拟机进程中,当这个进程开始的时候会启动一个主线程( MainThread ),在 Android 4.0 或以上的版本中,强制禁止在主线程执行耗时的网络操作,若需要进行网络操作,则需要另外开辟线程或使用 AsyncTask ,下面介绍的是另外开辟线程的方法。

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

	new Thread(postLoad).start();

}
	
Runnable postLoad = new Runnable(){
		  
	@Override
	public void run() {  
		// TODO Auto-generated method stub  
		// 在这里执行联网操作
	}
};

但是,联网操作后一般都需要根据联网所得数据更新 UI ,这时又会产生一个新问题,主线程负责处理和 UI 相关的操作,因此主线程又被称为 UI 线程。而 Android 采用 UI 单线程模型,只能在主线程中对 UI 元素进行操作,在非 UI 线程直接对 UI 进行了操作,则会报错。

为了解决这个问题,则需要利用 Android 的消息循环的机制实现线程间的通信。即在非 UI 线程发送消息到 UI 线程,让 UI 线程来进行 UI 的操作。例如,可以利用 View 的 post 方法告知 UI 线程执行操作更新 UI 。

Runnable postLoad = new Runnable(){
		  
	@Override
	public void run() {  
		// TODO Auto-generated method stub
		// 联网获取数据 data
		TextView textShow = (TextView) findViewById(R.id.show);
		textShow.post(new Runnable() {
		      
			@Override
			public void run() { // 该方法会在 ui 线程执行 
				textShow.setText(data);
			}
		});
	}
};

2. 检测是否有网络

final ConnectivityManager mConnectivity = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
// 检查网络连接,如果无网络可用,就不需要进行连网操作等 
NetworkInfo info = mConnectivity.getActiveNetworkInfo();    
if (info != null ) { // 若有网络
	// 判断网络连接类型
	int netType = info.getType(); 
	int netSubtype = info.getSubtype(); 

	if (netType == ConnectivityManager.TYPE_WIFI) { 
		// 若为 WIFI
	} else if (netType == ConnectivityManager.TYPE_MOBILE && netSubtype == TelephonyManager.NETWORK_TYPE_UMTS ) { 
		// 若为 3G
	} else { 
		// 其他网络
	}
} else { // 若无网络

}

3. 自定义 touch 创建左右划动检测

	
// 定义手势速度记录器
private VelocityTracker velocityTracker;
// 定义手势动作两点之间的距离要求
private static final int VELOCITYX = 900;
private static final int VELOCITYY = 800;

WebView postContent = (WebView) findViewById(R.id.postContent);

postContent.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View arg0, MotionEvent arg1) {
         // TODO Auto-generated method stub
	    	
        switch(arg1.getAction()){
        case MotionEvent.ACTION_DOWN:
           	if(velocityTracker == null){
           		// 取得手势在屏幕上的滑动速度
   			velocityTracker = VelocityTracker.obtain();
   			velocityTracker.addMovement(arg1);
   		}
   		break;
   	case MotionEvent.ACTION_MOVE:
   		if(velocityTracker != null){
   			velocityTracker.addMovement(arg1);
   		}
   		break;
        case MotionEvent.ACTION_CANCEL:
        case MotionEvent.ACTION_OUTSIDE:
           	break;
        case MotionEvent.ACTION_UP:

   		int velocityX = 0, velocityY = 0;

   		if(velocityTracker != null){
   			velocityTracker.addMovement(arg1);
   			velocityTracker.computeCurrentVelocity(1000); // 计算每秒滑动多少个像素
   			velocityX = (int) velocityTracker.getXVelocity(); // 最后计算检索 X 速度
   			velocityY = (int) velocityTracker.getYVelocity(); // 最后计算检索 Y 速度
   		}

    		// 从右向左划
   		if( velocityX < -VELOCITYX && velocityY < VELOCITYY && velocityY > -VELOCITYY ){
       			// 执行相应操作
       			return true;
       		} else if( velocityX > VELOCITYX && velocityY < VELOCITYY && velocityY > -VELOCITYY ) { // 从左向右划
       			// 执行相应操作
       			return true;
       		} else {
       			// 判断若不是划动操作,则返回 false 使用 WebView 自身的 touch 处理
       			return false;
       		}
    			
        }
        return false;
    }
});

在检测过程中发现触摸操作不完整(例如划动距离太少,或者误触屏幕),或是直接判断出不是划动操作,必须返回 false ,使到组件自身的 touch 处理得以保留。

本文由 Kayo Lee 发表,本文链接:http://kayosite.com/some-problems-of-android-development-part-two.html

评论列表

回复

你正在以游客身份访问网站,请输入你的昵称和 E-mail
:wink: :roll: :oops: :mrgreen: :idea: :cry: :?: :-| :-o :-P :-? :) :( 8-O