当前位置:   article > 正文

Android NDK中的UI线程_alooper_prepare

alooper_prepare

概述

在Android中,UI线程是一个很重要的概念。我们对UI的更新和一些系统行为,都必须在UI线程(主线程)中进行调用。

同时,我们在进行底层跨平台开发时,我们会选择NDK,在Linux系统上进行开发。在Linux中是没有主线程这一概念的。

那么,如果我们在子线程调用了一个native方法,在C++的代码中,我们想要切换到主线程调用某个方法时,该如何切换线程呢?

需求

众所周知,Toast消息,是无法在子线程调用的。如果我们在子线程中执行C++的代码,此时想调用toast方法,该如何是好呢?

  1. final String s = mEditTest.getText().toString();
  2. for (int i = 0 ; i < 3 ; i++){
  3. new Thread(new Runnable() {
  4. @Override
  5. public void run() {
  6. nativeToast(s);
  7. }
  8. }).start();
  9. }
  10. public native void nativeToast(String text);
  11. public static void toast(String text){
  12. Toast.makeText(MyAppImpl.getAppContext(), text, Toast.LENGTH_SHORT).show();
  13. }

在上面的代码中,native层的nativeToast其实就是调用了Java层的toast方法。只是在调用之前,做了线程的转换,在C++层的主线程调用了toast。

实现

初始化

MainActivity.java

  1. static {
  2. System.loadLibrary("native-lib");
  3. }
  4. Button mBtnTest;
  5. EditText mEditTest;
  6. @Override
  7. protected void onCreate(Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.activity_main);
  10. init();
  11. mBtnTest = findViewById(R.id.test_btn);
  12. mEditTest = findViewById(R.id.test_input);
  13. mBtnTest.setOnClickListener(new View.OnClickListener() {
  14. @Override
  15. public void onClick(View v) {
  16. final String s = mEditTest.getText().toString();
  17. for (int i = 0 ; i < 3 ; i++){
  18. new Thread(new Runnable() {
  19. @Override
  20. public void run() {
  21. nativeToast(s);
  22. }
  23. }).start();
  24. }
  25. }
  26. });
  27. }
  28. public native void init();

native-lib.cpp

  1. #include <jni.h>
  2. #include <string>
  3. #include "main_looper.h"
  4. #include "jvm_helper.h"
  5. extern "C"
  6. {
  7. JNIEXPORT void JNICALL
  8. Java_com_example_oceanlong_ndkmaintest_MainActivity_init(JNIEnv *env, jobject instance) {
  9. JniHelper::setJVM(env);
  10. MainLooper::GetInstance()->init();
  11. LOGD("init env : %p", env);
  12. }
  13. JNIEXPORT void JNICALL
  14. Java_com_example_oceanlong_ndkmaintest_MainActivity_nativeToast(JNIEnv *env, jobject instance,jstring text_) {
  15. const char* ctext = JniHelper::jstr2char(env, text_);
  16. LOGD("nativeToast : %s", ctext);
  17. MainLooper::GetInstance()->send(ctext);
  18. env->ReleaseStringUTFChars(text_, ctext);
  19. }
  20. }

初始化的代码中,其实只做了两件事情:

  • 缓存一个全局的JNIEnv *
  • 初始化native的looper

初始化必须在主线程中执行!

MainLooper的初始化

main_looper.h


                
声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号