Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/193.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android Kotlin协程:使一个线程执行代码,而另一个线程等待第一个线程完成_Android_Kotlin_Kotlin Coroutines - Fatal编程技术网

Android Kotlin协程:使一个线程执行代码,而另一个线程等待第一个线程完成

Android Kotlin协程:使一个线程执行代码,而另一个线程等待第一个线程完成,android,kotlin,kotlin-coroutines,Android,Kotlin,Kotlin Coroutines,我在Kotlin中找到了转换后的以下代码: import android.content.Context import android.os.Build import android.os.Handler import android.os.ParcelFileDescriptor import android.print.PrintAttributes.Resolution import android.print.PrintDocumentAdapter.LayoutResultCallba

我在Kotlin中找到了转换后的以下代码:

import android.content.Context
import android.os.Build
import android.os.Handler
import android.os.ParcelFileDescriptor
import android.print.PrintAttributes.Resolution
import android.print.PrintDocumentAdapter.LayoutResultCallback
import android.print.PrintDocumentAdapter.WriteResultCallback
import android.util.Log
import android.webkit.WebView
import android.webkit.WebViewClient
import java.io.File


/**
 * Converts HTML to PDF.
 *
 *
 * Can convert only one task at a time, any requests to do more conversions before
 * ending the current task are ignored.
 */
class PdfConverter private constructor() : Runnable {
    private var mContext: Context? = null
    private var mHtmlString: String? = null
    private var mPdfFile: File? = null
    private var mPdfPrintAttrs: PrintAttributes? = null
    private var mIsCurrentlyConverting = false
    private var mWebView: WebView? = null
    private var done: Boolean = false

    override fun run() {
        mWebView = WebView(mContext as Context)
        mWebView!!.webViewClient = object : WebViewClient() {
            override fun onPageFinished(view: WebView, url: String) {
                if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) throw RuntimeException(
                    "call requires API level 19"
                ) else {
                    val documentAdapter =
                        mWebView!!.createPrintDocumentAdapter()
                    documentAdapter.onLayout(
                        null,
                        pdfPrintAttrs,
                        null,
                        object : LayoutResultCallback() {},
                        null
                    )
                    documentAdapter.onWrite(
                        arrayOf(PageRange.ALL_PAGES),
                        outputFileDescriptor,
                        null,
                        object : WriteResultCallback() {
                            override fun onWriteFinished(pages: Array<PageRange>) {
                                destroy()
                                done = true
                            }
                        })

                }
                Log.d("end of onpagefinished()", "end of onpagefinished()")
            }
        }
        mWebView!!.loadData(mHtmlString, "text/HTML", "UTF-8")
        Log.d("end of run()", "end of run()")

    }


    var pdfPrintAttrs: PrintAttributes?
        get() = if (mPdfPrintAttrs != null) mPdfPrintAttrs else defaultPrintAttrs
        set(printAttrs) {
            mPdfPrintAttrs = printAttrs
        }

    fun convert(
        context: Context?,
        htmlString: String?,
        file: File?
    ) {
        requireNotNull(context) { "context can't be null" }
        requireNotNull(htmlString) { "htmlString can't be null" }
        requireNotNull(file) { "file can't be null" }
        if (mIsCurrentlyConverting) return
        mContext = context
        mHtmlString = htmlString
        mPdfFile = file
        mIsCurrentlyConverting = true
        runOnUiThread(this)
        Log.d("end of convert()","end of convert()")
    }

    private val outputFileDescriptor: ParcelFileDescriptor?
        private get() {
            try {
                mPdfFile!!.createNewFile()
                Log.d("outputfiledescriptor","the file has been created")
                return ParcelFileDescriptor.open(
                    mPdfFile,
                    ParcelFileDescriptor.MODE_TRUNCATE or ParcelFileDescriptor.MODE_READ_WRITE
                )
            } catch (e: Exception) {
                Log.d(TAG, "Failed to open ParcelFileDescriptor", e)
            }
            return null
        }

    private val defaultPrintAttrs: PrintAttributes?
        private get() = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) null else PrintAttributes.Builder()
            .setMediaSize(PrintAttributes.MediaSize.NA_GOVT_LETTER)
            .setResolution(Resolution("RESOLUTION_ID", "RESOLUTION_ID", 600, 600))
            .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
            .build()

    private fun runOnUiThread(runnable: Runnable) {
        val handler = Handler(mContext!!.mainLooper)
        handler.post(this)
    }

    private fun destroy() {
        mContext = null
        mHtmlString = null
        mPdfFile = null
        mPdfPrintAttrs = null
        mIsCurrentlyConverting = false
        mWebView = null
        Log.d("end of destroy()","end of destroy()")
    }

    companion object {
        private const val TAG = "PdfConverter"
        private var sInstance: PdfConverter? = null
        @get:Synchronized
        val instance: PdfConverter?
            get() {
                if (sInstance == null) sInstance =
                    PdfConverter()
                return sInstance
            }
    }
}
另外,在另一个文件中有一个函数调用PdfConverter,它调用
PdfConverter

fun createPdfFromHtml(htmlstring: String) {
       val converter: PdfConverter? = PdfConverter.instance
        val file = File(
            Environment.getExternalStorageDirectory().getPath().toString() + "/" + name_of_directory_of_pdfs + "/",
            nameofpdf
        )
        converter?.convert(m_context, htmlstring, file)
        mFilepdf = file
}
我想要的是代码执行在“converter?convert(m_context,htmlstring,file)”处停止,等待执行PdfConverter的“onWriteFinished”,然后继续。我认为的另一个senario是执行在“runonUiThread”处停止,等待“onWriteFinished”再次执行。

回答@m0skit0后,我更改最后一个代码:

fun createPdfFromHtml(htmlstring: String) {
        val file = File(
            Environment.getExternalStorageDirectory().path.toString() + "/" + name_of_directory_of_pdfs + "/",
            nameofpdf
        )
        var converter = PdfConverter3.from(m_context)
        GlobalScope.launch(Dispatchers.IO) {// I TRY ALSO Dispatchers.Main
           converter.convert(htmlstring, file)
        }
        mFilepdf = file
        Log.d("mich/createPDfFromHtml", "at the end of createPdfFromHtml, is this the main thread ? "+ (Looper.myLooper() == Looper.getMainLooper()))
}

但是这个东西又存在了。

如果我理解正确,您希望在主线程上执行run。为了实现这一点,您可以让函数
启动与Dispatchers.Main作用域的协程,而不是使run成为一个
挂起的
函数。

下面是我关于使用协程将该类转换为Kotlin的看法

package org.m0skit0.android.testapp

import android.annotation.TargetApi
import android.content.Context
import android.os.ParcelFileDescriptor
import android.print.PageRange
import android.print.PrintAttributes
import android.print.PrintDocumentAdapter
import android.webkit.WebView
import android.webkit.WebViewClient
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

@TargetApi(19)
class PdfConverter private constructor(private val context: Context) {

    private val defaultPrintAttributes: PrintAttributes by lazy {
        PrintAttributes.Builder()
            .setMediaSize(PrintAttributes.MediaSize.NA_GOVT_LETTER)
            .setResolution(PrintAttributes.Resolution("RESOLUTION_ID", "RESOLUTION_ID", 600, 600))
            .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
            .build()
    }

    private var printAttributes: PrintAttributes? = null

    fun printAttributes(printAttributes: PrintAttributes): PdfConverter = apply {
        this.printAttributes = printAttributes
    }

    suspend fun convert(htmlString: String, pdfFile: File) {
        withContext(Dispatchers.Main) {
            suspendCoroutine<Unit> { continuation ->
                WebView(context).apply {
                    webViewClient = WebViewClientImpl(pdfFile, continuation)
                }.loadData(htmlString, "text/html", "UTF-8")
            }
        }
    }

    private fun File.outputFileDescriptor(): ParcelFileDescriptor? =
        try {
            createNewFile()
            ParcelFileDescriptor.open(this, ParcelFileDescriptor.MODE_TRUNCATE or ParcelFileDescriptor.MODE_READ_WRITE)
        } catch (e: Exception) {
            null
        }

    companion object {
        fun from(context: Context): PdfConverter = PdfConverter(context)
    }

    private inner class WebViewClientImpl(private val file: File, private val continuation: Continuation<Unit>) : WebViewClient() {
        override fun onPageFinished(webView: WebView, url: String) {
            webView.createPrintDocumentAdapter()?.run {
                onLayout(
                    null,
                    printAttributes ?: defaultPrintAttributes,
                    null,
                    object : PrintDocumentAdapter.LayoutResultCallback() {},
                    null
                )
                onWrite(
                    arrayOf(PageRange.ALL_PAGES),
                    file.outputFileDescriptor(),
                    null,
                    object : PrintDocumentAdapter.WriteResultCallback() {
                        override fun onWriteCancelled() {
                            super.onWriteCancelled()
                            continuation.resume(Unit)
                        }

                        override fun onWriteFailed(error: CharSequence?) {
                            super.onWriteFailed(error)
                            continuation.resumeWithException(Exception(error.toString()))
                        }

                        override fun onWriteFinished(pages: Array<out PageRange>?) {
                            super.onWriteFinished(pages)
                            continuation.resume(Unit)
                        }
                    }
                )
            }
        }
    }
}
package org.m0skit0.android.testapp
导入android.annotation.TargetApi
导入android.content.Context
导入android.os.ParcelFileDescriptor
导入android.print.PageRange
导入android.print.printtributes
导入android.print.PrintDocumentAdapter
导入android.webkit.WebView
导入android.webkit.WebViewClient
导入kotlinx.coroutines.Dispatchers
导入kotlinx.coroutines.withContext
导入java.io.xml文件
导入kotlin.coroutines.Continuation
导入kotlin.coroutines.resume
导入kotlin.coroutines.resumeWithException
导入kotlin.coroutines.suspendCoroutine
@塔吉塔皮(19)
类PdfConverter私有构造函数(私有val上下文:上下文){
private val defaultPrintAttributes:惰性的PrintAttributes{
printtributes.Builder()
.setMediaSize(PrintAttributes.MediaSize.NA_政府信函)
.setResolution(PrintAttributes.Resolution(“Resolution_ID”,“Resolution_ID”,600600))
.setMinMargins(printtributes.Margins.NO_Margins)
.build()
}
私有变量printtributes:printtributes?=null
有趣的printtributes(printtributes:printtributes):PdfConverter=apply{
this.printtributes=printtributes
}
暂停趣味转换(htmlString:String,pdfFile:File){
withContext(Dispatchers.Main){
suspendCoroutine{continuation->
WebView(上下文)。应用{
webViewClient=WebViewClientImpl(PDF文件,续)
}.loadData(htmlString、“文本/html”、“UTF-8”)
}
}
}
private fun File.outputFileDescriptor():ParcelFileDescriptor=
试一试{
createNewFile()
打开(这是ParcelFileDescriptor.MODE\u TRUNCATE或ParcelFileDescriptor.MODE\u READ\u WRITE)
}捕获(e:例外){
无效的
}
伴星{
乐趣来自(上下文:上下文):PdfConverter=PdfConverter(上下文)
}
私有内部类WebViewClientImpl(私有val文件:文件,私有val延续:延续):WebViewClient(){
覆盖乐趣onPageFinished(webView:webView,url:String){
webView.createPrintDocumentAdapter()?。运行{
网上购物(
无效的
打印属性?:默认打印属性,
无效的
对象:PrintDocumentAdapter.LayoutResultCallback(){},
无效的
)
写(
数组(页面范围。所有页面),
file.outputFileDescriptor(),
无效的
对象:PrintDocumentAdapter.WriteResultCallback(){
重写onWriteCancelled(){
super.onWriteCancelled()
续.简历(单位)
}
重写onWriteFailed(错误:CharSequence?){
super.onWriteFailed(错误)
continuation.resumeWithException(异常(error.toString()))
}
重写已完成(页面:数组?){
super.onWriteFinished(页)
续.简历(单位)
}
}
)
}
}
}
}

您不能让UI线程等待。这将产生一个ANR。@m0skit0也许我没有说清楚。我希望UI线程执行“run”而不是等待。因为它与视图有关…执行后台任务的类不应该访问GUI元素。为什么不向这个类传递一个回调,它会在完成后通知您,然后您就可以在GUI中执行您想要执行的操作?一个类应该只有一个职责。@m0skit0。非常感谢你。还有一个问题,我想确定我明白了。“运行”函数不应从UI线程执行,因为它使用视图组件?因为我在某个地方读过它,我不记得它在哪里。@m0skit0查看原始Java源代码,该类在内部创建一个WebView以使用其功能创建PDF,然后处理该WebView。谢谢。我会试试看,然后回复。我试过了,但还是一样。。。while循环是一个无限循环。“onWriteFinished”从来没有因为某种原因被调用。好吧,我误解了你想要的,我编辑了我的答案。嗯,奇怪。如何调用convert()函数?剩余的代码必须在同一个协程中。convert()应挂起执行它的任何协程,这意味着该协程中的任何代码都不会继续执行,直到convert()调用continuation.resume,这是在WriteResultCallback上完成的。您能否指定“代码继续执行而不等待“onWriteFinished”执行”的含义?在协同程序之外的任何代码都将
package org.m0skit0.android.testapp

import android.annotation.TargetApi
import android.content.Context
import android.os.ParcelFileDescriptor
import android.print.PageRange
import android.print.PrintAttributes
import android.print.PrintDocumentAdapter
import android.webkit.WebView
import android.webkit.WebViewClient
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine

@TargetApi(19)
class PdfConverter private constructor(private val context: Context) {

    private val defaultPrintAttributes: PrintAttributes by lazy {
        PrintAttributes.Builder()
            .setMediaSize(PrintAttributes.MediaSize.NA_GOVT_LETTER)
            .setResolution(PrintAttributes.Resolution("RESOLUTION_ID", "RESOLUTION_ID", 600, 600))
            .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
            .build()
    }

    private var printAttributes: PrintAttributes? = null

    fun printAttributes(printAttributes: PrintAttributes): PdfConverter = apply {
        this.printAttributes = printAttributes
    }

    suspend fun convert(htmlString: String, pdfFile: File) {
        withContext(Dispatchers.Main) {
            suspendCoroutine<Unit> { continuation ->
                WebView(context).apply {
                    webViewClient = WebViewClientImpl(pdfFile, continuation)
                }.loadData(htmlString, "text/html", "UTF-8")
            }
        }
    }

    private fun File.outputFileDescriptor(): ParcelFileDescriptor? =
        try {
            createNewFile()
            ParcelFileDescriptor.open(this, ParcelFileDescriptor.MODE_TRUNCATE or ParcelFileDescriptor.MODE_READ_WRITE)
        } catch (e: Exception) {
            null
        }

    companion object {
        fun from(context: Context): PdfConverter = PdfConverter(context)
    }

    private inner class WebViewClientImpl(private val file: File, private val continuation: Continuation<Unit>) : WebViewClient() {
        override fun onPageFinished(webView: WebView, url: String) {
            webView.createPrintDocumentAdapter()?.run {
                onLayout(
                    null,
                    printAttributes ?: defaultPrintAttributes,
                    null,
                    object : PrintDocumentAdapter.LayoutResultCallback() {},
                    null
                )
                onWrite(
                    arrayOf(PageRange.ALL_PAGES),
                    file.outputFileDescriptor(),
                    null,
                    object : PrintDocumentAdapter.WriteResultCallback() {
                        override fun onWriteCancelled() {
                            super.onWriteCancelled()
                            continuation.resume(Unit)
                        }

                        override fun onWriteFailed(error: CharSequence?) {
                            super.onWriteFailed(error)
                            continuation.resumeWithException(Exception(error.toString()))
                        }

                        override fun onWriteFinished(pages: Array<out PageRange>?) {
                            super.onWriteFinished(pages)
                            continuation.resume(Unit)
                        }
                    }
                )
            }
        }
    }
}