Android WorkManager冻结UI
我有一个自定义工作人员,负责从API获取一些联系人,然后将这些联系人存储在手机的联系人列表中。此工作人员仍在冻结UI。任何帮助都将不胜感激 这是工人的嫁妆方法:Android WorkManager冻结UI,android,kotlin,worker,android-workmanager,Android,Kotlin,Worker,Android Workmanager,我有一个自定义工作人员,负责从API获取一些联系人,然后将这些联系人存储在手机的联系人列表中。此工作人员仍在冻结UI。任何帮助都将不胜感激 这是工人的嫁妆方法: override fun doWork(): Result { return try { makeStatusNotification("Saving Contacts", applicationContext, "WorkRequest Starting") //MAIN ME
override fun doWork(): Result {
return try {
makeStatusNotification("Saving Contacts", applicationContext, "WorkRequest Starting")
//MAIN METHOD CALL
if (!checkContactListEmpty()) {
removeAllContacts()
}
connectAndGetApiData()
val x = Data.Builder()
Result.success(x.build())
} catch (e: Exception) {
Log.e("NoWork","Unable to save image to Gallery $e")
Result.failure()
}
}
这是connectAndGetApi方法:
fun connectAndGetApiData() {
val BASE_URL = "HTTP_URL"
val res = Data.Builder()
allNames = object : ArrayList<String>(){}
allNumbers = object : ArrayList<String>(){}
Log.d("entering", "connecting")
if (retrofit == null) {
retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.build()
}
val contactsApiService: RestApi? = retrofit?.create(RestApi::class.java)
val call: Call<ContactList>? = contactsApiService?.getAllContactDetails()
call?.enqueue(object : Callback<ContactList> {
override fun onResponse(
call: Call<ContactList>,
response: Response<ContactList>
) {
Log.d("AllContacts",response.message())
val contactList: ContactList = response.body()
if(contactList!= null){
Log.d("AllContacts", contactList.allContacts.size.toString())
for(x in contactList.allContacts){
addContact(x.name,x.phoneNo)
Thread.sleep(50)
}
}else{
Log.d("AllContacts", "contacts null")
}
}
override fun onFailure(
call: Call<ContactList>,
throwable: Throwable
) {
val TAG = "AllContacts"
Log.e(TAG, throwable.toString())
}
})
}
fun connectAndGetApiData(){
val BASE_URL=“HTTP_URL”
val res=Data.Builder()
allNames=object:ArrayList(){}
allNumbers=object:ArrayList(){}
日志d(“进入”、“连接”)
如果(改装==null){
改装=改装.Builder()
.baseUrl(基本URL)
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.build()
}
val contactsApiService:RestApi?=改装?.create(RestApi::class.java)
val call:call?=ContactsAspiService?.getAllContactDetails()
call?.enqueue(对象:Callback){
覆盖响应(
呼叫:呼叫,,
答复:答复
) {
Log.d(“所有联系人”,response.message())
val contactList:contactList=response.body()
如果(联系人列表!=null){
Log.d(“AllContacts”,contactList.AllContacts.size.toString())
用于(联系人列表中的x。所有联系人){
addContact(x.name,x.phoneNo)
线程。睡眠(50)
}
}否则{
Log.d(“所有联系人”,“联系人为空”)
}
}
覆盖故障(
呼叫:呼叫,,
可以扔掉的
) {
val TAG=“所有联系人”
Log.e(标记,throwable.toString())
}
})
}
removeAllContacts()是删除所有联系人的标准函数
Api产生了大约22000个联系人
编辑:
这是addContact()方法
private fun addContact(姓名:String?,号码:String?){
var finalName=“”
val finalNumber=数字
if(name?.isEmpty()==true){
val tsLong=System.currentTimeMillis()/1000
val ts=tsLong.toString()
finalName=“非名称$ts”
}否则{
finalName=name.toString()
finalName=finalName.substring(1,(finalName.length-2))
}
val ops=ArrayList()
val rawContactID:Int=ops.size
补充行动(
ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT\u URI)
.withValue(contacts contract.raw contacts.ACCOUNT_TYPE,null)
.withValue(contacts contract.raw contacts.ACCOUNT\u NAME,null)
.build()
)
补充行动(
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT\u URI)
.带ValueBackReference(contacts contract.Data.RAW\u CONTACT\u ID,RAW contactId)
.withValue(contacts contract.Data.MIMETYPE、contacts contract.commonDataTypes.StructuredName.CONTENT\u ITEM\u TYPE)
.withValue(contacts contract.CommonDataTypes.StructuredName.DISPLAY\u NAME,finalName)
.build()
)
补充行动(
ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT\u URI)
.带ValueBackReference(contacts contract.Data.RAW\u CONTACT\u ID,RAW contactId)
.withValue(contacts contract.Data.MIMETYPE、contacts contract.commondatatypes.Phone.CONTENT\u ITEM\u TYPE)
.带值(contacts contract.commondatatypes.Phone.NUMBER,finalNumber)
.withValue(contacts contract.commondatatypes.Phone.TYPE,contacts contract.commondatatypes.Phone.TYPE\u MOBILE)
.build()
//
)
尝试{//将所有插入操作作为单个数据库事务执行
对数d(
“添加联系人”,“姓名:$finalName号码:$finalNumber”
)
applicationContext.contentResolver.applyBatch(contacts contract.AUTHORITY,ops)
线程。睡眠(50)
Log.d(“已保存联系人”、“已保存”)
}catch(e:RemoteException){
e、 printStackTrace()
}捕获(e:操作应用程序异常){
e、 printStackTrace()
}
}
当此改装调用在主线程之外完成时,回调在主线程上
i、 e.call?.enqueue(对象:Callback{
在此回调中执行的任何操作都将在UI线程上执行
您可以执行以下代码:
for(x in contactList.allContacts){
addContact(x.name,x.phoneNo)
Thread.sleep(50)
}
对于列表中的每个联系人,它都会让UI线程休眠50毫秒。评论中说哪个有22000个项目
如果要处理如此大的数据集,需要使用后台线程
一个快速而肮脏的解决方案是: 使用协同程序:
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"
interface ContactsApiService {
@GET("whateverYourEndPointIs")
suspend fun getAllApiDetails(): Response<ContactList>
}
将改装更改为使用协同程序:
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"
interface ContactsApiService {
@GET("whateverYourEndPointIs")
suspend fun getAllApiDetails(): Response<ContactList>
}
接口接触器{
@获取(“无论您的端点是什么”)
suspend fun GetAllapDetails():响应
}
在后台线程上运行这一切:
GlobalScope.launch {
val response: Response<ContactList> = contactsApiService?.getAllContactDetails()
Log.d("AllContacts",response.message())
val contactList: ContactList = response.body()
if (contactList!= null) {
Log.d("AllContacts", contactList.allContacts.size.toString())
for(x in contactList.allContacts){
addContact(x.name,x.phoneNo)
delay(50)
}
} else {
Log.d("AllContacts", "contacts null")
}
}
GlobalScope.launch{
val response:response=contactsApiService?.getAllContactDetails()
Log.d(“所有联系人”,response.message())
val contactList:contactList=response.body()
如果(联系人列表!=null){
Log.d(“AllContacts”,contactList.AllContacts.size.toString())
用于(联系人列表中的x。所有联系人){
addContact(x.name,x.phoneNo)
延迟(50)
}
}否则{
Log.d(“所有联系人”,“联系人为空”)
}
}
哪个函数挂起UI connectAndGetApiData()或removeAllContacts()?connecAndGetApiData()方法冻结UI您的addContact
函数是否在后台线程上运行?似乎是在获取22000个联系人的列表后(在后台线程上使用改型队列)您正在迭代22000个项目,并在addContact
函数中执行一些工作(我不知道它是做什么的)。addContact函数也在worker类中定义,并在那里调用,因此是的,addContact函数在后台运行