本机调用阻塞主线程
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了本机调用阻塞主线程相关的知识,希望对你有一定的参考价值。
我有一些android应用程序应该在启动时加载一些数据并尽快处理它。为了在本机代码中完成更好的性能数据处理。但是在一段时间内,数据量增加了,并且在处理时变为阻止UI。奇怪的是我从后台线程启动JNI调用,我相信本机代码也应该在后台工作。这么几个问题:
- 如何检测原生代码在主线程中工作?
- 如何检测谁阻止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在<unistd.h>中定义了系统调用getpid()和gettid()。如果pid_t返回值相等,那么您的本机代码将在UI线程上运行。
我为此目的使用BlockCanary。如果您了解LeakCanary
,BlockCanary
会以相同的方式提供有关UI阻止的报告。
如何检测本机代码在主线程中工作?
您可以在代码中应用Log方法。
例如,您的代码是:
if(myInt > 0){
doSth();
}
插入日志方法;
if(myInt > 0){
doSth();
Log.i("Info", "if statement is true.");
}
现在,如果if语句运行,您的设备将键入控制台。因此,在您的线程中,您可以将Log方法插入关键行以查看它是否正在运行。
如何检测谁阻止UI?
在我的第一个答案中,如果您在代码中实现Log方法,您可以再次从控制台中看到它。
但是如果你想要正确地做,我建议你检查Asynctask。这需要时间来学习如何正确实现它,但是在Android中将长作业传递到后台的最实用的方法是Asynctask。
以上是关于本机调用阻塞主线程的主要内容,如果未能解决你的问题,请参考以下文章
从后台线程调用 startActivity 并且主线程被阻塞时,Activity 延迟启动
在辅助线程中调用 select()/pselect() 会导致主线程阻塞吗?
CompletableFutureCompletableFuture测试runAsync()方法调用CompletableFuture.join()/get()方法阻塞主线程
cordova 3.0 FileWriter 线程警告:对 File.write 的 exec() 调用阻塞了主线程...应该使用 CordovaInterface.getThreadPool()