当前位置:  编程技术>移动开发
本页文章导读:
    ▪Activity与Thread其间的通讯(old)        Activity与Thread之间的通讯(old) 在Android中要让Activity与Thread进行通讯 其实很简单。重点就在于android .os.Handler、java.lang.Thread以及android.os.Message这三个类的整合应用 我们在Thread中可以通过Mes.........
    ▪ Thread,Looper,Handler,Message,MessageQueue,MessagePool其间的关系        Thread,Looper,Handler,Message,MessageQueue,MessagePool之间的关系 多线程与异步Main Thread & UI Thread当程序启动的时候Android会自动创建一个进程和一个线程,这个线程负责界面更新,收集系统事件和用户.........
    ▪ 判别苹果翻新机       识别苹果翻新机 苹果官方的退回(Refurbished)机器,修好后再卖出的包装都是OEM包装,不是正规的彩色零售版包装,同时会有Apple官方的Refurbished证明,享受苹果官方1年或者AppleCare 3年保修.........

[1]Activity与Thread其间的通讯(old)
    来源: 互联网  发布时间: 2014-02-18
Activity与Thread之间的通讯(old)
在Android中要让Activity与Thread进行通讯 其实很简单。
重点就在于android .os.Handler、java.lang.Thread以及android.os.Message这三个类的整合应用
我们在Thread中可以通过Message来通知Handler,Handler在这里扮演着联系Acitivity与Thread之间的角色。

首先在Acitivity中我们要定义 一个常量来作为判断标示
private static final int GUINOTIFIER = 0x1234;
然后定义一些例子 里面需要的属性
public Calendar mCalendar;
public int mMinutes;
public int mHour;
public Handler mHandler;
private Thread mClockThread;
接着我们通过Handler来接收Thread所传递的信息
mHandler = new Handler() {
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case TestHandler.GUINOTIFIER://TestHandler是Activity的类名
                        //得到Handle的通知了 这个时候你可以做相应的操作,本例是使用TextView 来显示时间
                        mTextView .setText(mHour + " : " + mMinutes);
                        break;
                }
                super.handleMessage(msg);
            }
        };

接下来我们自定义一个Thread
class LooperThread extends Thread {
        public void run() {
            super.run();
            try {
                do {//每间隔一秒取一次系统 时间
                    long time = System.currentTimeMillis();
                    final Calendar mCalendar = Calendar.getInstance();
                    mCalendar.setTimeInMillis(time);
                    mHour = mCalendar.get(Calendar.HOUR);
                    mMinutes = mCalendar.get(Calendar.MINUTE);
                    Thread.sleep(1000);
                    //取得系统时间后发送消息给Handler
                    Message m = new Message();
                    m.what = Ex04_14.GUINOTIFIER;
                    Ex04_14.this.mHandler.sendMessage(m);
                } while (!LooperThread.interrupted());//当系统发出终端命令时停止循环
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

最后我们启动线程
mClockThread = new LooperThread();
mClockThread.start();
复制代码
利用上面的例子我们可以扩展更多的应用,比如使用Thread进行上传下载 操作,完成后通知主Activity等等

    
[2] Thread,Looper,Handler,Message,MessageQueue,MessagePool其间的关系
    来源: 互联网  发布时间: 2014-02-18
Thread,Looper,Handler,Message,MessageQueue,MessagePool之间的关系

多线程与异步
Main Thread & UI Thread
当程序启动的时候Android会自动创建一个进程和一个线程,这个线程负责界面更新,收集系统事件和用户的操作事件等并分配给对应的组件,所以这个线程非常重要 被称为主线程,因为所的和UI有关的操作都是在这个线程当中进行的所以也被称作UI线程。所以说默认情况下主线程和UI线程指的是同一个线程。For instance, when the user touches a button on the screen, your app's UI thread dispatches the touch event to the widget, which in turn sets its pressed state and posts an invalidate request to the event queue. The UI thread dequeues the request and notifies the widget that it should redraw itself.

Android的UI系统参考了很多SWT的设计模式。比如,UI线程机制,底层JNI实现 etc.

Android 的UI系统是非线程安全的,意思是说只有创建UI的线程(也就是主线程)才可以对UI进程操作。如果我们在其它线程中执行了一些操作,而这些操作的结果又需要通过UI展现给用户,必需把这更新UI的操作转移到到UI线程中执行。

很多Java起步的程序员对UI线程中的"消息循环"会感觉陌生。其实就是在线程内部有一个死循环一直监听系统事件(用户的操作等)并把任务分发给对应的组件(有兴趣的可以看看NDK附带的native-activity的一个sample,在c中的实现方式就是一个while(1)的死循环)。主线程通过Looper实现了消息的循环处理。

The ralationship between Handler,Message,MessageQueue and Looper?
如果一个线程里边有一个死循环,那么这个循环就会一直在死循环里边循环,并且这个线程不会过多的cpu资源,那么这个线程肯定的阻塞的。如果线程只是一直循环没有什么意义,实际情况通常需要线程根据不同的条件运行不同的方法。我们通常的作法可能会加一个switch开关,根据条件的不同去调用不同的方法。

线程间通信(最常见的就是,worker线程需要更新UI),这个时候实际是包含两个内容:一,数据的传递;二,方法的传递; Android中的Message用于数据传递,而Handler就是方法传递(其实是方法的执行者,Handler会把这个方法放到Handler所在的线程当中去执行);MessageQueue是Message的容器和Java中的Queue一样都是容器,只不过Message Queue是专门用于装载Message的容器。Looper则是一个线程中的死循环用于管理MessageQueue,它负责阻塞读取MessageQueue中的信息(如果MessageQueue中没有信息会一直在那里),挨个读取并把这个Message分发给对应的Handler去执行。

通过一个小例子+源码追踪下它们之间是怎么工作的,关系是什么样的

public class HandleMessageTrackActivity extends Activity {
		final static int SHOW_ALERT = 1025;
		Activity mActivity;
		TextView displayText;
		Handler mHandler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				switch (msg.what) {
				case SHOW_ALERT:
					showAlert((String) msg.obj);
					break;
				}
			}
		};

		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			mActivity = this;
			displayText = new TextView(this);
			setContentView(displayText);
			displayText.setText("Just ignore me");
			new Thread() {
				@Override
				public void run() {
					String Greetings = "Greetings from another Thread";
					mHandler.obtainMessage(SHOW_ALERT, Greetings)
							.sendToTarget();
				}
			}.start();
		}

		private void showAlert(String content) {
			AlertDialog.Builder builder = new Builder(mActivity);
			builder.setMessage(content);
			builder.create().show();
		}
	}


首先看一下mHandler.obtainMessage(SHOW_ALERT, Greetings).sendToTarget();会执行什么。 通过查看Handler的源码发现执行了下边的代码。

	public final Message obtainMessage(int what, Object obj) {
		return Message.obtain(this, what, obj);
	}



接着查看Message中的代码,
	public static Message obtain(Handler h, int what, Object obj) {
		Message m = obtain();
		m.target = h;
		m.what = what;
		m.obj = obj;
		return m;
	}

	/***
	 * Return a new Message instance from the global pool. Allows us to* avoid
	 * allocating new objects in many cases.
	 */
	public static Message obtain() {
		synchronized (mPoolSync) {
			if (mPool != null) {
				Message m = mPool;
				mPool = m.next;
				m.next = null;
				return m;
			}
		}
		return new Message();
	}


看到这里我们应该明白为什么Google建议我们使用obtainMessage而不是new一个Message.这也是符合了Android中的对象回收机制。

public void sendToTarget() {  
		//targe就是一个Handler
		target.sendMessage(this);
	}
	//sendMessage()会调用下面的sendMessageAtTime()把Message加入MessagQueue;
	public boolean sendMessageAtTime(Message msg, long uptimeMillis){ 
		boolean sent = false; 
		MessageQueue queue = mQueue;  
		if (queue != null) {     
			msg.target = this;     
			sent = queue.enqueueMessage(msg, uptimeMillis);    
			}else {   
				RuntimeException e = new RuntimeException(    
						this + " sendMessageAtTime() called with no mQueue");    
				Log.w("Looper", e.getMessage(), e);   
				} 
		return sent;
		}
	}

到此我们的Message对象被加入到了Handler所在线程(也就是主线程)中的MessageQueue这个存储和管理Message的容器当中。下一步就该由Looper接手一个一个的取出Message对象处理了。Looper最主要的方法就是loop()方法

Looper me = myLooper();  
		MessageQueue queue = me.mQueue; 
		while (true) {//死循环 
			Message msg = queue.next(); // might block     
			if (msg != null) {         
				if (msg.target == null) {//退出死循环的机制    
					// No target is a magic identifier for the quit message.      
					return;      
					}    
				if (me.mLogging!= null)
					me.mLogging.println(">>>>> Dispatching to " + msg.target + " "    + msg.callback + ": " + msg.what );      
				msg.target.dispatchMessage(msg);//target of a msg is a Handler  
				if (me.mLogging!= null) me.mLogging.println(       
						" Finished to    " + msg.target + " "     
				+ msg.callback);//msg.callback is a Runnable      
				msg.recycle();    
				}  
			}
		}
				}
			}
		}
	}


Looper会一直阻塞读取MessagQueue中的Message对象(Message msg = queue.next()),当读取到一个Message时就会调用msg.target.dispatchMessage(msg)把这个Message分发给对应的Handler去处理,等Handler把任务处理完了再接着读取下一个Message对象并处理。

	/*** Handle system messages here.*/
	public void dispatchMessage(Message msg) { 
		if (msg.callback != null) {      
			handleCallback(msg);
			// call the run method of the runnable object I guess   
			} else {     
				if (mCallback != null) {  
					if (mCallback.handleMessage(msg)) 
					{         
						return; 
						}      
					}      
				handleMessage(msg);
				}
		}
		}
	}


最后回来了我们的handlerMessage(msg);这个方法中。如果是用的不是sendMessage是是Hadler.post(Runnable)会调用

private final void handleCallback(Message message) {    message.callback.run();}
这就是为什么在Handler中post的Runnable不会开启一个新的线程的原因。经过上面的追踪我们应该能明白不是所有 的线程都可以有Handler去执行handlerMessage或者处理Runnalbe的。其必要条件就是这个线程要有一个一直循环的Looper.Looper一直循环肯定要有一个方法可以退出循环。
public void quit() {    Message msg = Message.obtain();    // NOTE: By enqueueing directly into the message queue, the    // message is left with a null target.  This is how we know it is    // a quit message.    mQueue.enqueueMessage(msg, 0);}


当我们调用msg.sendToTarget()的时候,我们的msg对象应付被压入MessageQueue的尾部。Looper在MessageQueue的另一端一个一个的读取信息并处理。根据msg的target属性把cpu分配给对应的Handler去执行任务,这时Handler会根据msg中的属性调用msg.handleMsg()或者msg.callback.run();当一个msg中的消息处理完返回之后Looper会把这个msg放入msgPool当中方便下次再重复利用。从而减少对象的创建。Looper再从MessageQueue中读取下一个信息,如此反复。。

理解了这些其实就不难想象ANR是如何实现的了。当用户执行操作(比如点击了一个按钮)系统会生成一个Message对象,把用户操作的信息写入Message对象,并把这个Message对象压入MessageQueue队列的尾部。系统过一段时间(一般是五秒)后会再来检查,刚刚放入的信息是不是已经被处理了,如果信息还在队列中就表明。处理前面信息的过程当中发生的阻塞,用户的操作没有及时得到响应。系统弹出ANR对话框。

作个总结:

  因为UI线程需要保持一直运行的状态,所以要有一个循环保持这个线程不会死掉,但这个线程又必需阻塞,以减少cpu的消耗。android中的这个循环就是通过Looper实现的。有了这个 Looper,Looper就占据了整个线程,导致所有的方法想在些线程中运行就必需通过这个Looper,所以要有个方法可以进入这个Looper的内部。MessageQueue就担当了这个通道 的角色。Message担当了集合的角色。所有在UI线程中运行的方法都必需通过MessageQueue进入Looper内部,不管 是用户定义的方法还是系统事件包括onCreate(),onStop(),用户点击事件etc..

MessageQueue包含两个方法,next()和enquenceMessage(),一个用于读取message,一个用于写入message,它们的访问都是通过jni访问的C层,message也是存储在C层的。在next方法中,如果messagequeue中没有消息,则进入wait。在写入消息时,再进行唤醒操作
1 楼 ChenJavaNet 2012-03-04  
很有研究精神 跟你学习了

    
[3] 判别苹果翻新机
    来源: 互联网  发布时间: 2014-02-18
识别苹果翻新机

苹果官方的退回(Refurbished)机器,修好后再卖出的包装都是OEM包装,不是正规的彩色零售版包装,同时会有Apple官方的Refurbished证明,享受苹果官方1年或者AppleCare 3年保修。后缀不限。

 

而私人翻新,这就说不准了,各种后缀都回有。

买苹果,请认准:

1. 零售包装,没有开过封(即笔记本外层保护膜没有北开过封,电池循环次数为0-1,箱子未被二次封装)

2. 翻修包装,带有Apple的资格认证,享受官方保修,并且能够在官方查到。

 

凭序列号,在如下连接查找

https://selfsolve.apple.com/GetWarranty.do

//***********************************************************ip4

二、三码合一

  很多朋友可能都听说过“三码合一”,这三码指的是iPhone盒子背面塑封膜外贴着的S/N码和SIM卡托上的金属S/N码,以及iPhone系统设置》通用》关于本机项里的S/N码。如果是国行全新机,这三码必须合一。对于港水或者其他地区的水货机,三码合一的难度比较大,相应的留给JS钻空子的机会也很大。

  同时我们需要注意,iPhone盒子背面塑封膜外的S/N码贴纸,是最容易被JS们使用自制的贴码换掉,我们只要用手使劲的搓一下这张S/N纸,如果出现字迹模糊,那基本可以断定是JS替换过的。

      如果检查过上述两个方面没有问题,我们开始从包装里拿出iPhone时,不要急着立即开机使用。我们先检查检查iPhone4的机器硬件外观上,从蛛丝马迹中,看看能不能发现翻新机的证据出来。

  iPhone4的新机上,正反面都会跟机贴着一张硬塑料卡,以在运输过程中为iPhone4提供足够防护。硬塑料卡与iPhone的贴合应该很紧密,机身上下卡片都不会突出。如果你拿到的是一个歪歪斜斜贴着塑料卡的“新手机”,你大可以转身就走。

  除了这张塑料卡之外,我们可以观察iPhone4的数据接口和耳机插孔。这两个接口应该是没有使用过的痕迹,没有灰尘和划痕。耳机插孔在光的照射下,应该显示银白色,而不是红色进水标志。

  iPhone4机身下方的两颗螺丝有没有拧动过的痕迹也很重要,这两颗螺丝在早期是十字形的,最近出厂的基本都是梅花形状。

  iPhone4的机身配件是否被更换也很重要,虽然这两样配件的售价不高,但对于翻新机来说,配置的很可能是山寨版的数据线。原装的数据线和耳机,绕线清晰摆放整齐。线材没有异味,线缆做工精致,接头处没有任何毛边。而国行的充电器是类似Macbook笔记本的方形充电器,港版是英制的大三角插头,而美制的是绿点充电器(充电插头附近有一绿色圆点)。这是区别三种版本很重要的依据。

四、软件验证

  其实无论是从外观上,还是硬件上,想要识别现在越来越成熟的翻新手段,对于普通消费者来说都是比较困难的。但幸而苹果为我们提供了完善的手机信息软件查询手段,我们可以通过这些软件方法,识破那些伪装最严密的翻新机。

  最有效的方法,就是苹果官方的激活时间查询。在苹果官网中,苹果为我们提供了查询iPhone手机激活信息和保修信息的方法。通过访问这个网址:selfsolve.apple.com/GetWarranty.do,我们可以通过输入机器的序列号,查询到机器的激活时间和保修信息。一般来说,全新机是在这里查询不到记录的。这里查询的日期,应该是你首次打开手机,连接电脑激活使用的日期前后1至3天时间。


    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
oracle iis7站长之家
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3