本机调用阻塞主线程

时间:2017-12-29 13:49:48

标签: android multithreading java-native-interface

我有一些Android应用程序应该在启动时加载一些数据并尽快处理它。为了在本机代码中完成更好的性能数据处理。 但是在一段时间内,数据量增加了,并且在处理时变为阻止UI。奇怪的是我从后台线程启动JNI调用,我相信本机代码也应该在后台工作。 这么几个问题:

  1. 如何检测原生代码在主线程中工作?
  2. 如何检测谁阻止了用户界面?
  3. 一些代码示例:

            // java
            new Thread(new Runnable() {
                @Override
                public void run() {
                  ResourceLoader.loadListsAndParse(); // native call
                }
            }).start();
    
    
    // c++
    void RulesManager::loadRules() {
       if (!rules_loaded_) {
            using namespace std;
            base::FilePath my_dir;
            GetCacheDirectory(&my_dir);
            this->loadRulesInternal(my_dir, true);
       }
    }
    
    void RulesManager::loadRulesInternal(base::FilePath& path, bool processExceptions) {
       base::FileEnumerator files(path, false, base::FileEnumerator::FILES);
       for (base::FilePath name = files.Next(); !name.empty(); name = files.Next()) {
            this->loadRulesFromFile(name.AsUTF8Unsafe(), processExceptions);
       }
    }
    
    bool RulesManager::loadRulesFromFile(const std::string& filePath, bool processException) {
        bool result = false;
        std::ifstream file(filePath);
        std::string str;
        while (std::getline(file, str)) {
            result = this->addRule(str, processException);
        }
        return result;
    }
    

3 个答案:

答案 0 :(得分:2)

Android在< unistd.h> 中定义了系统调用 getpid() gettid()。如果 pid_t 返回值相等,那么您的本机代码将在UI线程上运行。

答案 1 :(得分:1)

我出于此目的使用BlockCanary。如果您了解LeakCanaryBlockCanary会以相同的方式提供有关UI阻止的报告。

enter image description here

答案 2 :(得分:1)

  

如何检测本机代码是否在主线程中工作?

您可以在代码中应用Log方法。

例如,您的代码是:

if(myInt > 0){
  doSth();
}

插入日志方法;

if(myInt > 0){
 doSth();
 Log.i("Info", "if statement is true.");
}

现在,如果if语句运行,您的设备将键入控制台。因此,在您的线程中,您可以将Log方法插入关键行以查看它是否正在运行。

  

如何检测谁阻止UI?

在我的第一个回答中,如果您在代码中实现Log方法,则可以再次从控制台中看到它。

但是如果你想要正确地做,我建议你检查Asynctask。这需要时间来学习如何正确实现它,但在Android中将长作业传递到后台的最实用的方法是Asynctask。