手机
当前位置:查字典教程网 >编程开发 >安卓软件开发 >深入Android线程的相关问题解惑
深入Android线程的相关问题解惑
摘要:一个应用只有一个线程在默认情况下,更确切的讲一个进程中只有一个线程,这跟其他语言,比如C/C++,Java等是一致。也就是说在Android...

一个应用只有一个线程

在默认情况下,更确切的讲一个进程中只有一个线程,这跟其他语言,比如C/C++,Java等是一致。也就是说在Android应用程序里面一个进程只有一个线程,所有组件都运行在一个线程里面!

当应用程序启动时,系统会为其创建一个进程,也会创建一个线程名字叫做main,所有其所属组件的创建,系统事件的处理,系统的回调等一切应用相关的事情都运行在此名叫main的线程中。此线程即为常说的主线程(main thread)。俗称的UI线程(UI thread)也是它,因为只有主线程可以操作UI相关的事情,所以有人把主线程也称作UI线程,但这并不是正确的说法,因为Service所属的线程也可以操作Toast,但是Service并没有UI。为什么非主线程不能操作UI呢?因为对UI操作常常会引发系统的回调,所以如果允许第三线程来操作可能会引发系统回调的紊乱,进而会打乱整个框架的时序!

这里要特别注意的就是同一个进程中的所有组件运行在同一个线程中,Activiy,Service,BoradcastReceiver和ContentProvider都运行在主线程中。

最容易引起误解的就是Service,文档和常识都会认为Service是放在后台用于操作费时运算的,但是实则不然,如果你在Service中做费时操作,同样会引发臭名昭著的ANR(Application Not Responding)。所以如果想把Service当做一个Server,必须在Service用HandlerThread或Thread创建一个Worker线程!

Activity也是一样的,你startActivity()后,开启了一个新的Activity,但它们都运行在同一个线程中,所以你还是不能在原Activity中做费时操作!也即在调用startActivity()开启了一个新的Activity后,或者在onPause(), onStop(), onDestroy()中做费时操作会引发ANR。

对于ContentProvider也是一样的,如果跟其他组件在同一进程内,那么调用ContentResolver的方法会相当于直接调用ContentProvider的方法。如果是在另外一个进程中,虽是通过IPC,但也是同步的,因为IBinder的同步的,也即调用ContentResolver时会把调用者的进程挂起,等待ContentProvider的进程操作结束,再把结果传给调用者进程!所以,如果ContentProvider中有费时操作,或者会同步锁数据库等,也一定要注意ANR的发生!

所以一定要记住:一个进程只有一个线程,所有组件都运行在主线程中。

因此,如果有费时操作,必须要创建Worker线程!

深入Android线程的相关问题解惑1

实例

下面有一个小实例,一个应用中有五个组件:2个Activity,一个Service,一个ContentProvider和一个BroadcastReceiver。在每个组件的方法中都有打印所属线程信息,另外对于Activity,Service和ContentProvider如果做费时操作会引发ANR,对于BroadcastReceiver更是如此,这个大家都懂得的!

复制代码 代码如下:

public class ActivityDemo extends Activity {

private static final String TAG = "ActivityDemo";

private Handler mMainHandler = new Handler(new Handler.Callback() {

public boolean handleMessage(Message msg) {

dumpThreadInfo();

return false;

}

});

@Override

protected void onCreate(Bundle savedInstanceState) {

dumpThreadInfo();

super.onCreate(savedInstanceState);

// add four buttons

LinearLayout layout = new LinearLayout(getApplication());

layout.setOrientation(LinearLayout.VERTICAL);

Button startService = new Button(getApplication());

startService.setText("Start a Service");

startService.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {

Intent i = new Intent(getApplication(), ServiceDemo.class);

startService(i);

}

});

layout.addView(startService);

Button startAnother = new Button(getApplication());

startAnother.setText("Start another Activity");

startAnother.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {

Intent i = new Intent(getApplication(), AnotherActivity.class);

startService(i);

}

});

layout.addView(startAnother);

Button startContentProvider = new Button(getApplication());

startContentProvider.setText("Start a ContentProvider");

startContentProvider.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {

getContentResolver().query(ContentProviderDemo.CONTENT_URI, null, null, null, null);

}

});

layout.addView(startContentProvider);

Button startReceiver = new Button(getApplication());

startReceiver.setText("Start a BroadcastReceiver");

startReceiver.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {

Intent i = new Intent("android.action.start_broadcastreceiver_demo");

sendBroadcast(i);

}

});

layout.addView(startReceiver);

setContentView(layout);

mMainHandler.sendEmptyMessageDelayed(0, 500);

}

public void dumpThreadInfo() {

Thread.dumpStack();

Log.e(TAG, Thread.currentThread().toString());

Log.e(TAG, " " + getMainLooper());

}

}

复制代码 代码如下:

public class AnotherActivity extends Activity {

private static final String TAG = "AnotherActivity";

private Handler mMainHandler = new Handler(getMainLooper(), new Handler.Callback() {

public boolean handleMessage(Message msg) {

// this will cause ANR

Log.e(TAG, "you know what this is very slow slow slow slow");

SystemClock.sleep(20 * 1000);

dumpThreadInfo();

return false;

}

});

@Override

protected void onCreate(Bundle savedInstanceState) {

dumpThreadInfo();

super.onCreate(savedInstanceState);

setTitle("this is another activity");

mMainHandler.sendEmptyMessageDelayed(0, 500);

}

@Override

protected void onDestroy() {

dumpThreadInfo();

super.onDestroy();

}

public void dumpThreadInfo() {

Thread.dumpStack();

Log.e(TAG, Thread.currentThread().toString());

Log.e(TAG, " " + getMainLooper());

}

}

复制代码 代码如下:

public class ServiceDemo extends Service {

private Handler mMainHandler = new Handler(new Handler.Callback() {

public boolean handleMessage(Message msg) {

// this will cause ANR, too

Log.e(TAG, "this is very slow you know, slow slow");

SystemClock.sleep(20 * 1000);

dumpThreadInfo();

return false;

}

});

private static final String TAG = "ServiceDemo";

@Override

public IBinder onBind(Intent arg0) {

dumpThreadInfo();

return null;

}

@Override

public void onCreate() {

dumpThreadInfo();

super.onCreate();

mMainHandler.sendEmptyMessageDelayed(0, 500);

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

dumpThreadInfo();

return super.onStartCommand(intent, flags, startId);

}

public void dumpThreadInfo() {

Thread.dumpStack();

Log.e(TAG, Thread.currentThread().toString());

Log.e(TAG, " " + getMainLooper());

}

}

复制代码 代码如下:

public class ContentProviderDemo extends ContentProvider {

public static final Uri CONTENT_URI = Uri.parse("content://com.hilton.effectiveandroid.app/content");

private static final String TAG = "ContentProviderDemo";

@Override

public int delete(Uri arg0, String arg1, String[] arg2) {

dumpThreadInfo();

return 0;

}

@Override

public Uri insert(Uri uri, ContentValues values) {

dumpThreadInfo();

return null;

}

@Override

public boolean onCreate() {

dumpThreadInfo();

return false;

}

@Override

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {

dumpThreadInfo();

// it will cause ANR of course

Log.e(TAG, "this is very slow, you know that");

SystemClock.sleep(20 * 1000);

return null;

}

@Override

public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {

dumpThreadInfo();

return 0;

}

public void dumpThreadInfo() {

Thread.dumpStack();

Log.e(TAG, Thread.currentThread().toString());

}

@Override

public String getType(Uri arg0) {

return null;

}

}

复制代码 代码如下:

public class BroadcastReceiverDemo extends BroadcastReceiver {

private static final String TAG = "BroadcastReceiverDemo";

@Override

public void onReceive(Context context, Intent intent) {

Log.e(TAG, "intent is " + intent);

dumpThreadInfo();

}

public void dumpThreadInfo() {

Thread.dumpStack();

Log.e(TAG, Thread.currentThread().toString());

}

}

【深入Android线程的相关问题解惑】相关文章:

Android:多线程之图文混排

Android相册效果

Android 使用XML做动画UI的深入解析

Android加载图片内存溢出问题解决方法

Android颜色编辑器的制作中遇到的问题分析

Android内存调试命令

Android 检索相册视频文件

Android:多线程之进程与线程

基于Android中实现定时器的3种解决方法

Android 编程下字库的使用及注意事项

精品推荐
分类导航