1

我正在使用自定義RenderScript腳本進行圖像處理的應用程序。現在,由於我有很多這些腳本正在使用,我將它們預先加載到應用程序首次啓動。通過「預加載」我的意思是我實例化每個腳本,以便它可以在設備上編譯。波紋是這個操作的代碼片段。大約有60個腳本,但我認爲這足以說明操作。Renderscript ScriptC編譯阻止主線程

public class Load extends Thread { 

    public Load() { 
     super(); 
     setPriority(Thread.MIN_PRIORITY); 
    } 

    @Override 
    public void run() { 
     new ScriptC_first(RenderScriptHelper.getInstance()); 
     new ScriptC_second(RenderScriptHelper.getInstance()); 
     new ScriptC_third(RenderScriptHelper.getInstance()); 
    } 
} 

正如你所看到的,我是在後臺線程上這樣做的。問題在於腳本似乎在主線程上編譯,無論如何。問題是他們阻止了用戶界面。我已經嘗試了與AsyncTask和服務相同的結果。我懷疑RenderScript內部在主線程上跳轉以編譯它們。

現在,在Android Nougat(7.0)之前,根據設備速度的不同,預加載相同數量的腳本的時間不到10秒。在牛軋糖上花費近一分鐘的時間,這是一個巨大的問題,考慮到它阻止了用戶界面,儘管只是第一次啓動應用程序。在隨後的每次啓動時,它都會在幾秒鐘之內預加載(因爲腳本已經編譯完成)。

我需要預加載,因爲根據需要實例化腳本不是一個選項,因爲所有腳本必須在用戶開始使用該應用程序後進行編譯和編譯。所述的logcat的

相關部分:

E/RenderScript: Unable to open shared library (/data/user/0/com.company.myapp/cache/librs.contrast_v001.so): undefined symbol: .rs.dtor 
V/RenderScript: Invoking /system/bin/bcc with args '/system/bin/bcc -unroll-runtime -scalarize-load-store -rs-global-info -rs-global-info-skip-constant -o contrast_v001 -output_path /data/user/0/com.company.myapp/cache -bclib /system/lib/libclcore.bc -mtriple armv7-none-linux-gnueabi -O 3 -load libbccQTI.so -fPIC -embedRSInfo /data/user/0/com.company.myapp/cache/contrast_v001.bc -build-checksum abadcafe' 
V/RenderScript: Invoking /system/bin/ld.mc with args '/system/bin/ld.mc -shared -nostdlib /system/lib/libcompiler_rt.so -mtriple=armv7-none-linux-gnueabi --library-path=/system/vendor/lib --library-path=/system/lib -lRSDriver_adreno -lm -lc /data/user/0/com.company.myapp/cache/contrast_v001.o -o /data/user/0/com.company.myapp/cache/librs.contrast_v001.so' 

另外,如果相關的我在第一個應用程序開始和RenderScript.ContextType.NORMAL在以後每次啓動使用RenderScript.ContextType.PROFILE。使用RenderScript.ContextType.DEBUG使腳本彙編關於每個應用程序開始,以相同的時間量作爲其他上下文中,並且輸出的logcat略有不同:

V/RenderScript: Invoking /system/bin/bcc with args '/system/bin/bcc -unroll-runtime -scalarize-load-store -rs-global-info -rs-global-info-skip-constant -o contrast_v001 -output_path /data/user/0/com.company.myapp/cache -bclib /system/lib/libclcore_debug.bc -mtriple armv7-none-linux-gnueabi -O 3 -rs-debug-ctx -fPIC -embedRSInfo /data/user/0/com.company.myapp/cache/contrast_v001.bc -build-checksum abadcafe' 
V/RenderScript: Invoking /system/bin/ld.mc with args '/system/bin/ld.mc -shared -nostdlib /system/lib/libcompiler_rt.so -mtriple=armv7-none-linux-gnueabi --library-path=/system/vendor/lib --library-path=/system/lib -lRSDriver_adreno -lm -lc /data/user/0/com.company.myapp/cache/contrast_v001.o -o /data/user/0/com.company.myapp/cache/librs.contrast_v001.so' 

的build.gradle的相關部分:

renderscriptTargetApi 23 
renderscriptSupportModeEnabled true 

我搜索了關於RenderScript內部工作的文檔和信息,但它確實很少,因爲大部分內部工作都由設備供應商自行決定。

所以我的問題是:是否有可能強制RenderScript在後臺線程上編譯腳本,而不會阻塞UI。

任何幫助表示讚賞。

回答

2

對於任何人誰遇到這樣的問題:我設法解決與應用中的私有進程中運行的服務的問題,聲明如:

<service 
    android:name="com.company.LoadService" 
    android:process=":loadService" 
    android:exported="false" /> 

我實例內的ScriptC_something.class-ES服務,並且由於它是一個獨立的進程,我的UI線程再次免費。

希望這可以幫助別人。