kotlin 为什么获取主机名作为字符串资源会给我NullPointerException?

mlmc2os5  于 2023-05-01  发布在  Kotlin
关注(0)|答案(1)|浏览(175)

当启动应用程序时,我试图创建首选项并编辑其值。getDefaultHostName()方法引发Null指针异常。下面是一个代码示例,如果有人可以帮助。
谢谢你。

val pref = PreferenceManager.getDefaultSharedPreferences(this)
        if (TextUtils.isEmpty(pref.getString(Utils.PREFS_HOST_NAME, null))) {
            // No preferences found. Save default values.
            val editor = pref.edit()
            editor.putString(Utils.PREFS_HOST_NAME, getDefaultHostName())
            editor.putBoolean(Utils.PREFS_USE_TLS, getDefaultTLS())
            editor.apply()
        }
private val sContext: MyApp? = null
fun getDefaultHostName(): String {
        return sContext!!.resources
            .getString(if (isEmulator()) R.string.emulator_host_name else R.string.default_host_name)
    }
<string name="default_host_name">Default host name</string>

Application类扩展DefaultLifecycleObserver

class MyApp : Application(), DefaultLifecycleObserver {

    lateinit var userPreferences: UserPreferencesRepository
    private val sContext: MyApp? = null

    private var sContactsObserver: ContentObserver? = null

    // The Tinode cache is linked from here so it's never garbage collected.
    private val sCache: Cache? = null

    private var sVideoCache: SimpleCache? = null

    private var sAppVersion: String? = null
    private var sAppBuild = 0

    companion object {
        var simpleCache: SimpleCache? = null
        private val TAG: String =
            GLOBAL_TAG + " " + MyApp::class.java.simpleName

        @get:Synchronized
        lateinit var instance: MyApp private set
        /*Vid*/
        // 256 MB.
        private val PICASSO_CACHE_SIZE: Int = 1024 * 1024 * 256
        private val VIDEO_CACHE_SIZE = 1024 * 1024 * 256

        private var sContactsObserver: ContentObserver? = null

        // The Tinode cache is linked from here so it's never garbage collected.
        private var sCache: Cache? = null

        private var sVideoCache: SimpleCache? = null
    }
}
override fun onCreate() {
        super<Application>.onCreate()
        instance = this
        try {
            val pi = packageManager.getPackageInfo(packageName, 0)
            instance.sAppVersion = pi.versionName
            if (TextUtils.isEmpty(instance.sAppVersion)) {
                instance.sAppVersion = BuildConfig.VERSION_NAME
            }
            instance.sAppBuild = pi.versionCode
            if (instance.sAppBuild <= 0) {
                instance.sAppBuild = BuildConfig.VERSION_CODE
            }
        } catch (e: PackageManager.NameNotFoundException) {
            Log.w(MyApp.TAG, "Failed to retrieve app version", e)
        }
        FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(!BuildConfig.DEBUG)
        val br: BroadcastReceiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {
                val token = intent.getStringExtra("token")
                if (token != null && token != "") {
                    Cache.tinode!!.setDeviceToken(token)
                }
            }
        }
        val lbm = LocalBroadcastManager.getInstance(this)
        lbm.registerReceiver(br, IntentFilter("FCM_REFRESH_TOKEN"))
        lbm.registerReceiver(
            HangUpBroadcastReceiver(),
            IntentFilter(Const.INTENT_ACTION_CALL_CLOSE)
        )
        createNotificationChannels()
        ProcessLifecycleOwner.get().lifecycle.addObserver(this)

        val pref = PreferenceManager.getDefaultSharedPreferences(this)
        if (TextUtils.isEmpty(pref.getString(Utils.PREFS_HOST_NAME, null))) {
            val editor = pref.edit()
            editor.putString(Utils.PREFS_HOST_NAME, getDefaultHostName())
            editor.putBoolean(Utils.PREFS_USE_TLS, getDefaultTLS())
            editor.apply()
        }
        WorkManager.getInstance(this).pruneWork()

        val client: OkHttpClient = OkHttpClient.Builder()
            .cache(
                okhttp3.Cache(
                    createDefaultCacheDir(this)!!,
                    MyApp.PICASSO_CACHE_SIZE.toLong()
                )
            )
            .addInterceptor(Interceptor { chain: Interceptor.Chain ->
                val tinode: Tinode = Cache.tinode!!
                val picassoReq = chain.request()
                val headers: Map<String?, String?>
                if (tinode.isTrustedURL(picassoReq.url.toUrl())) {
                    headers = tinode.requestHeaders
                    var builder: okhttp3.Request.Builder = picassoReq.newBuilder()
                    for ((key, value) in headers) {
                        builder = builder.addHeader(key, value)
                    }
                    return@Interceptor chain.proceed(builder.build())
                } else {
                    return@Interceptor chain.proceed(picassoReq)
                }
            })
            .build()
        Picasso.setSingletonInstance(Picasso.Builder(this)
            .requestTransformer { request: Request ->
                if (request.uri != null && Tinode.isUrlRelative(request.uri.toString())) {
                    val url: URL = Cache.tinode!!.toAbsoluteURL(request.uri.toString())!!
                    if (url != null) {
                        return@requestTransformer request.buildUpon()
                            .setUri(Uri.parse(url.toString())).build()
                    }
                }
                request
            }
            .downloader(OkHttp3Downloader(client))
            .build())

        val cm = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
            ?: return
        val req =
            NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .build()
        cm.registerNetworkCallback(req, object : ConnectivityManager.NetworkCallback() {
            override fun onAvailable(network: Network) {
                super.onAvailable(network)
                if (!TextUtils.isEmpty(BaseDb.instance!!.uid)) {
                    // Connect right away if UID is available.
                    Cache.tinode!!.reconnectNow(true, false, false)
                }
            }
        })
    }

获取上下文方法

fun getAppContext(): Context? {
        return sContext
    }

过程: www.example. com ,PID:31344 java.lang.RuntimeException:无法创建应用程序com。elto.date.lightDark.MyApp:java.android中的lang.NullPointerException。app.ActivityThread.handleBindApplication(ActivityThread.java:7109)。app.ActivityThread.access$1600(ActivityThread.java:271)在android.app.ActivityThread$H。handleMessage(ActivityThread.java:2134)在android上。os.Handler.dispatchMessage(Handler.java:106)在android.os.Looper.loopOnce(Looper.java:210)在android上。os.Looper.loop(Looper.java:299)在android.app.ActivityThread.main(ActivityThread.java:8319)。lang.reflect.方法.invoke(本机方法)在com.android.internal.os.RuntimeInit$ www.example.com (RuntimeInit.java:556)在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1038)原因:java.lang.NullPointerException at com.elto.date.lightDark.getDefaultHostName(MyApp.KT:240)在com.elto.date.lightDark.onCreate(MyApp.KT:141)在Android上。app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1212)在android上。app.ActivityThread.handleBindApplication(ActivityThread.java:7103)。app.ActivityThread.access$1600(ActivityThread.java:271)在android.app.ActivityThread$H。handleMessage(ActivityThread.java:2134)在android上。os.Handler.dispatchMessage(Handler.java:106)在android.os.Looper.loopOnce(Looper.java:210)在android上。os.Looper.loop(Looper.java:299)在android.app.ActivityThread.main(ActivityThread.java:8319)。lang.reflect.方法.invoke(本机方法)在com.android.internal.os.RuntimeInit$ www.example.com (RuntimeInit.java:556)在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1038)

yzuktlbb

yzuktlbb1#

为什么获取主机名作为字符串资源会给我NullPointerException?
据我所知,您的代码中没有初始化sContext属性。因此,当在getDefaultHostName()内部执行sContext!!时,会抛出NullPointerException。要修复它,您应该初始化sContext,可能在MyApp.onCreate()内部。

相关问题