继续整理一下做 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 发表,本文链接:https://kayosite.com/some-problems-of-android-development-part-two.html
评论列表
技术文章啊~看不懂~有前途~ 😉
搞安卓开发的现在工资很高!
我同学做安卓测试的,我程序菜鸟