本机调用阻塞主线程

问题描述 投票:1回答:3

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

  1. 如何检测原生代码在主线程中工作?
  2. 如何检测谁阻止UI?

一些代码示例:

        // 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;
}
android multithreading java-native-interface
3个回答
2
投票

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


1
投票

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

enter image description here


1
投票

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

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

例如,您的代码是:

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

插入日志方法;

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

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

如何检测谁阻止UI?

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

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

© www.soinside.com 2019 - 2024. All rights reserved.