RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / user-238742

Andrew's questions

Martin Hope
Andrew
Asked: 2022-08-29 14:26:58 +0000 UTC

如何正确处理 MVVM 中的方向变化?

  • 1

有一个活动和一些片段。每个片段都可以访问 ViewModel。问题是在旋转设备并返回片段后,observable 会触发两次。这是视图模型:

class AppViewModel(private val mainRepository: MainRepository) : ViewModel() {
//поле которое обновляется
val userInfo: MutableLiveData<Any> by lazy {
   MutableLiveData<Any>()
}
...

//метод который обновляет поле
fun getUserInfo() {
...
}

}

在 Fragment 中使用 ViewModel:

class PersonalPage : Fragment(R.layout.fragment_personal_page) {

lateinit var viewModel: AppViewModel

override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        viewBinding = FragmentPersonalPageBinding.inflate(inflater, container, false)
        viewBinding!!.lifecycleOwner = viewLifecycleOwner
        val retrofitService = RetrofitService.getInstance(requireContext())
        val mainRepository = MainRepository(retrofitService)
        viewModel = ViewModelProvider(
            requireActivity(),
            AppVMFactory(mainRepository)
        )[AppViewModel::class.java]

        return viewBinding!!.root
    }

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

            viewModel.userInfo.observe(viewLifecycleOwner) {
                it?.let {
                    if (it is UserInfo) {
                        println("viewmodel fetch")
                        ...
                    }
                }
            }
            viewModel.getUserInfo()
       }
   ....
}

处理活动中的屏幕旋转以返回片段:

supportFragmentManager.findFragmentByTag("personal_page")?.let {
                    transaction.replace(R.id.contentContainer, it,"personal_page").commit()
                } ?: run {
                    transaction.replace(R.id.contentContainer, personalPage,"personal_page").commit()
                }

试图在旋转时移除监听器:

viewModel.userInfo.removeObservers(viewLifecycleOwner)

没有那样工作。尝试通过完全分配 null 来杀死视图模型 - 没有用。尽管我在调试下查看并且我在堆栈上有一份片段副本,也就是说,没有重复。是否有可能在屏幕旋转后以某种方式删除变量的侦听器,或者是否有另一种方法来处理一般的方向变化?或者,您可以在旋转后删除片段,然后再次切换到它,而不用标签搜索片段,但我认为这是错误的。

android
  • 1 个回答
  • 45 Views
Martin Hope
Andrew
Asked: 2020-06-18 22:13:51 +0000 UTC

RV 适配器中对话框标记的奇怪行为

  • 1

有这个标记:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginBottom="20dp"
    android:orientation="vertical">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/dialog_background">

        <TextView
            android:id="@+id/txt_view1"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_alignParentTop="true"
            android:gravity="center_horizontal|center_vertical"
            android:text="@string/change_status"
            android:textColor="@color/gray"
            android:textSize="16sp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <View
            android:id="@+id/view1"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/test_color"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@id/txt_view1" />

        <ListView
            android:id="@+id/status_list"
            android:layout_width="match_parent"
            android:layout_height="400dp"
            android:overScrollMode="never"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@id/view1"/>

        <View
            android:id="@+id/view2"
            android:layout_width="match_parent"
            android:layout_height="0.8dp"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@id/status_list"
            android:background="@color/test_color" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toBottomOf="@id/view2"
            android:orientation="horizontal"
            android:weightSum="10">

            <TextView
                android:id="@+id/remove_note"
                android:layout_width="0dp"
                android:layout_height="50dp"
                android:layout_weight="4.98"
                android:gravity="center_vertical|center_horizontal"
                android:text="@string/delete_mess"
                android:textColor="#CD0000"
                android:textSize="16sp" />

            <View
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="0.04"
                android:background="@color/test_color" />

            <TextView
                android:id="@+id/add_note_to_archive"
                android:layout_width="0dp"
                android:layout_height="50dp"
                android:layout_weight="4.98"
                android:gravity="center_vertical|center_horizontal"
                android:text="@string/archive_menu_item"
                android:textColor="@color/gray"
                android:textSize="16sp" />
        </LinearLayout>


    </androidx.constraintlayout.widget.ConstraintLayout>

    <TextView
        android:id="@+id/cancel_dialog"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="10dp"
        android:background="@drawable/dialog_background"
        android:gravity="center_horizontal|center_vertical"
        android:text="@android:string/cancel"
        android:textColor="@color/colorAccent"
        android:textSize="16sp" />


</LinearLayout>

片段中有一个列表及其适配器。列表元素有一个视图,单击时会显示一个对话框:

holder.changeStatusTv.setOnClickListener {
            val dialogue = Dialog(ctx)
            dialogue.setContentView(R.layout.note_status_dialogue)

            val window = dialogue.window
            val wlp = window!!.attributes
            wlp.gravity = Gravity.BOTTOM
            window.attributes = wlp

            dialogue.findViewById<View>(R.id.remove_note).setOnClickListener {
                showDialogue(1, recordModel.id, holder.adapterPosition)
                dialogue.dismiss()
            }

            dialogue.findViewById<View>(R.id.add_note_to_archive).setOnClickListener {
                showDialogue(2, recordModel.id, holder.adapterPosition)
                dialogue.dismiss()
            }

            if (statusList[0] == ctx.resources.getString(R.string.all_records_notepad)) {
                statusList.removeAt(0)
            }


            val list: ListView = dialogue.findViewById(R.id.status_list)


            for (i in 0 until statusList.size) {
                if (statusList.size > ctx.resources.getStringArray(R.array.basic_status_list).size) {
                    if (i < ctx.resources.getStringArray(R.array.basic_status_list).size) {
                        if (statusList[i] == ctx.resources.getStringArray(R.array.basic_status_list)[i]) {
                            statusList[i] = ctx.resources.getStringArray(R.array.status_list)[i]
                        }
                    }
                } else {
                    if (statusList[i] == ctx.resources.getStringArray(R.array.basic_status_list)[i]) {
                        statusList[i] = ctx.resources.getStringArray(R.array.status_list)[i]
                    }
                }

            }


            list.adapter = ArrayAdapter(ctx, R.layout.note_status_layout, R.id.textItem, statusList)

            list.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ ->
                changeStatus(recordModel.id, position)
                dialogue.dismiss()
            }

            dialogue.setCanceledOnTouchOutside(false)
            dialogue.findViewById<View>(R.id.cancel_dialog).setOnClickListener {
                dialogue.dismiss()
            }

            Objects.requireNonNull<Window>(dialogue.window).setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
            dialogue.show()
        }

问题的本质是在api版本为26(8.0)的模拟器上,这个对话框被正确放置在父级的宽高中:

在此处输入图像描述

而在 api 版本 28 (9.0) 的模拟器上,对话框是根据父级的高度放置的,而宽度的行为令人费解:

在此处输入图像描述

然后我在真实设备上尝试:android 10.0 和 6.0.1,情况与第二个模拟器上的情况相同,尽管轴的版本不同。总的来说,我无法理解这个布局发生了什么,也许有人会有建议或某处有错误?)

android
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-04-30 20:05:29 +0000 UTC

什么是 okhttp3 错误以及如何解决?

  • 0

我正在尝试实现这样的事情:通过文件选择器选择了一个文件,我将它翻译成一个字符串,并在聊天中以 10k 字节为单位将其发送到服务器。以下是选择和剪切文件的方式:

requestCode == 1 && resultCode == Activity.RESULT_OK -> {
                if (data != null) {
                    val fileUri = data.data!!
                    val partSize = 10000
                    val fileString = readTextFile(fileUri)
                    var name = ""
                    var size: Long? = null

                    fileUri.let { returnUri ->
                        contentResolver.query(returnUri, null, null, null, null)
                    }?.use { cursor ->
                        val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
                        val sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE)
                        cursor.moveToFirst()
                        name = cursor.getString(nameIndex)
                        size = cursor.getLong(sizeIndex)
                    }



                    if (fileString!!.length < partSize) {
                        ws.send(ChatRequestMessages.sendFile(fileString,
                                name,
                                selectedContactId.toString(),
                                fileString.length.toLong(),
                                0))
                    } else {
                        val partsCount = if (size!!.rem(partSize).toInt() == 0) {
                            size!!.div(partSize)
                        } else {
                            size!!.div(partSize)
                        }


                        for (currentPart in 0..size!!.div(partSize)) {
                            val slicedString = if ((currentPart + 1) * partSize <= size!!.toInt()) {
                                fileString.substring(currentPart.toInt() * partSize..(currentPart + 1).toInt() * partSize)
                            } else {
                                fileString!!.substring(currentPart.toInt() * partSize until fileString.length)
                            }

                            Timber.i("${fileString.length.toLong()}  ${currentPart * partSize} ${slicedString.length} $slicedString $name")



                            ws.send(ChatRequestMessages.sendFile(slicedString,
                                    name,
                                    selectedContactId.toString(),
                                    fileString.length.toLong(),
                                    (currentPart * partSize).toInt()))
                        }
                    }


                }
            }

然后出现一个奇怪的情况:例如14字节的文件,一切正常发送,3 kb的文件也可以,但是当我尝试发送12.15 kb的文件时,出现以下错误:

[okio.RealBufferedSource.require(RealBufferedSource.kt:201), okio.RealBufferedSource.readByte(RealBufferedSource.kt:210), okhttp3.internal.ws.WebSocketReader.readHeader(WebSocketReader.kt:119), okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.kt:102), okhttp3.internal.ws.RealWebSocket.loopReader(RealWebSocket.kt:293), okhttp3.internal.ws.RealWebSocket$connect$1.onResponse(RealWebSocket.kt:195), okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:504), java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162), java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636), java.lang.Thread.run(Thread.java:764)] 

当我发送一个 120kb 的文件时,我收到以下错误:

Read error: ssl=0xdbda0ac0: I/O error during system call, Connection reset by peer null [com.android.org.conscrypt.NativeCrypto.SSL_read(Native Method), com.android.org.conscrypt.OpenSSLSocketImpl$SSLInputStream.read(OpenSSLSocketImpl.java:741), okio.InputStreamSource.read(JvmOkio.kt:90), okio.AsyncTimeout$source$1.read(AsyncTimeout.kt:129), okio.RealBufferedSource.request(RealBufferedSource.kt:207), okio.RealBufferedSource.require(RealBufferedSource.kt:201), okio.RealBufferedSource.readByte(RealBufferedSource.kt:210), okhttp3.internal.ws.WebSocketReader.readHeader(WebSocketReader.kt:119), okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.kt:102), okhttp3.internal.ws.RealWebSocket.loopReader(RealWebSocket.kt:293), okhttp3.internal.ws.RealWebSocket$connect$1.onResponse(RealWebSocket.kt:195), okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:504), java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162), java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636), java.lang.Thread.run(Thread.java:764)] 

我不明白出了什么问题,什么影响了文件大小。也许有人有类似的问题,他解决了,我将不胜感激任何信息:)

android
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-04-28 20:28:26 +0000 UTC

“切片”字符串 kotlin 出错

  • 1

通过选择文件时,onActivityResult()我想将其“剪切”成碎片。为此,我读取了它的字节:

val fileUri = data.data!!
val string = fileUri.let { uri -> contentResolver.openInputStream(uri).use { it!!.readBytes() } }

我正在切片:

val partSize = 10000
val partsCount = if (size.rem(partSize).toInt() == 0) {
    size.div(partSize).toInt()
} else {
    size.div(partSize).toInt() + 1
}

for (i in 0 until partsCount) {

val slicedString: ByteArray = if ((i + 1) * partSize < i * partSize + size.rem(partSize).toInt()) {
    string.slice(i * partSize..(i + 1) * partSize).toByteArray()
} else {
    string.slice(i * partSize..i * partSize + size.rem(partSize).toInt()).toByteArray()
}

}

现在实际的问题是:文件大小127036和我的应用程序因错误而崩溃:

java.lang.IndexOutOfBoundsException: toIndex (127037) is greater than size (127036)

问题是 - 又一个字节是从哪里来的,以及如何删除它?也许它是某种空间或需要移除的隐形字符trim()?如果我们将通常的输出带到索引控制台进行切片,那么一切都很好:

if ((i + 1) * partSize < i * partSize + size.rem(partSize).toInt()) {
Timber.i((i * partSize..(i + 1) * partSize).toString())
} else {
Timber.i((i * partSize..i * partSize + size.rem(partSize).toInt()).toString())
}

我认为问题出在size.rem(partSize).toInt(). 舍入失败,因为 long 已通过并且文档只有 double/int。还有一个想法是移位一位:

size.rem(partSize).shr(1).toInt()

但不确定这是否是正确的解决方案。

android
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-03-27 01:03:02 +0000 UTC

正确形成 json-string kotlin

  • 0

我需要这样写一行:

{"chat": {"a": "get_history"}}

尝试这样做:

val getHistory = JSONStringer().`object`().key("chat")
.value(JSONStringer().`object`().key("a").value("get_history").endObject().toString().replace("\'", "")).endObject().toString()

像这样尝试过:

val jsonFormattedString = JSONTokener(jsonObject.toString()).nextValue().toString()
val jsonObject2 = JsonObject()
jsonObject2.addProperty("chat", jsonFormattedString)

结果总是这样:

{"chat":"{\"a\":\"get_history\"}"}

虽然这部分结果是:

{"a":"get_history"}

我试图以这种方式删除它,.replace("\\\'", "")最后没有任何反应。您如何实现最初需要的选项?

更新

最糟糕的工作选择:

val testValue: MutableMap<String, String> = HashMap()
testValue["chat"] = JSONStringer().`object`().key("a").value("get_history").endObject().toString()

然后得到这样的字符串:

testValue.toString().replace("=",":")

也许有人会有一些意见)

json
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-03-21 00:03:51 +0000 UTC

如何与类似js android的websocket通信?

  • 0

有一段js代码:

token = 'some_data';
sid = 'some_data';
ws = new WebSocket('some_data' + sid + '/');
ws.onmessage = function(resp){console.log(resp)};
ws.send(JSON.stringify({'token':token}));
ws.send(JSON.stringify({'chat':{'a':'init', 'rtc_supported': false}}));
ws.send(JSON.stringify({'chat':{'a':'send', 'to': '03654ps', 'body':'preved', 'stamp': 0}}));

我正在尝试通过 okHttp 连接到服务器:

val loggingInterceptor: HttpLoggingInterceptor = HttpLoggingInterceptor()
    .setLevel(HttpLoggingInterceptor.Level.BODY)


val client = OkHttpClient.Builder()
    .connectTimeout(60, TimeUnit.SECONDS)
    .writeTimeout(300, TimeUnit.SECONDS)
    .addInterceptor(loggingInterceptor)
    .readTimeout(60, TimeUnit.SECONDS)
    .build()

val json = "application/json; charset=utf-8".toMediaTypeOrNull()
val params: MutableMap<String, String> = HashMap()
params["token"] = getSharedPreferences("app_data", 0).getString("access_token", "")!!
val parameter = JSONObject(params as Map<*, *>)

val body: RequestBody = parameter.toString().toRequestBody(json)

val request = Request.Builder()
    .url(CHAT_URL)
    .post(body)
    .build()


val webSocket = client.newWebSocket(request, EchoWebSocketListener())

client.dispatcher.executorService.shutdown()

如果我理解正确,那么没有令牌,我的服务器将不会返回任何内容。我添加了一个令牌,您可以从请求正文中的代码中理解:

val json = "application/json; charset=utf-8".toMediaTypeOrNull()
val params: MutableMap<String, String> = HashMap()
params["token"] = getSharedPreferences("app_data", 0).getString("access_token", "")!!
val parameter = JSONObject(params as Map<*, *>)

val body: RequestBody = parameter.toString().toRequestBody(json)

但是如果我这样做,我会得到这个错误:

java.lang.IllegalArgumentException: Request must be GET: POST

要么这些事情根本不是那样做的,要么我做错了什么。服务器地址本身如下所示:

wss://test_server.net:4433/ws/jwt/jfagdod

我不知道我哪里出了问题以及如何解决它。

javascript
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-03-19 18:10:04 +0000 UTC

聊天写安卓

  • 1

有一个任务 - 在android上写一个聊天。还有一个聊天服务器。据我了解,一切都需要在套接字上完成。但是我不知道从哪里开始 :( 首先,很难找到一个可以正常工作的库或一种可以提供预期结果的方法。我希望可以通过scarletfrom 完成所有工作,Tinder但是出了点问题,并且依赖关系没有充分连接。将所需的java版本设置为.后出现很多问题。build.gradle有很多库,甚至更多的手工方法,但由于服务器地址使用协议而大部分都消失了http/https,我使用wss.目前,我的最后一次尝试是从这里进行的,请求也没有发送:

val wsFactory = WebSocketFactory()
                .createSocket("wss://server/")
                .addHeader("token", context!!.getSharedPreferences("app_data", 0).getString("access_token", "")!!)

或者我无法理解创建聊天的原则。我以前做过改造,也许我期待正常的请求响应行为。但从我读到的内容来看,这里的一切都以大致相同的方式实现。也有这样的尝试:

private fun instantiateWebSocket() {
        val client = OkHttpClient()
        val request: Request = Request.Builder()
                .url("wss://server/")
                .addHeader("token", context!!.getSharedPreferences("app_data", 0).getString("access_token", "")!!)
                .build()


        Timber.i(request.toString())

        val socketListener = SocketListener(context!!)
        webSocket = client.newWebSocket(request, socketListener)
        webSocket!!.send("0909")

    }

    class SocketListener(cont: Context) : WebSocketListener() {
        var context: Context = cont
        override fun onOpen(webSocket: WebSocket, response: Response) {
            Timber.i(response.toString())
            Runnable { Toast.makeText(context, "Connection Established!", Toast.LENGTH_LONG).show() }
        }

        override fun onMessage(webSocket: WebSocket, text: String) {
            val jsonObject = JSONObject()
            try {
                jsonObject.put("message", text)
                jsonObject.put("byServer", true)
            } catch (e: JSONException) {
                e.printStackTrace()
            }

        }

        init {
            this.context = cont
        }
    }

在这里也没有发送请求。我究竟做错了什么?也许有人有创建聊天的经验并有工作方式?

android
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-03-05 20:05:10 +0000 UTC

如何在拦截器android改造中取消请求?

  • 1

有这样一个拦截器:

class AuthToken(context: Context) : Interceptor {
    var cont = context
    override fun intercept(chain: Interceptor.Chain): Response {
        val sp = cont.getSharedPreferences("app_data", 0)
        val originalRequest:Request? = (if (sp!!.getLong("expires_in", 0) - sp.getLong("time_delta", 0) - System.currentTimeMillis() / 1000 <= 60) {
            updateToken(chain)
            null
        } else {
            chain.request()
                    .newBuilder()
                    .header("Content-type:", "application/json")
                    .header("Authorization", "Bearer " + cont.getSharedPreferences("app_data", 0).getString("access_token", "")!!)
                    .build()
        })


        if (originalRequest!=null){
            val response = chain.proceed(originalRequest)
            when (response.code) {
                401 -> {
                    updateToken(chain)
                }
                500 -> {
                    Toast.makeText(cont, cont.getString(R.string.server_error_500), Toast.LENGTH_SHORT).show()
                }
            }


            return response
        }else chain.proceed(originalRequest)

    }


    private fun updateToken(request: Interceptor.Chain) {
        val interceptor = HttpLoggingInterceptor()
        interceptor.level = HttpLoggingInterceptor.Level.BODY

        val dispatcher = Dispatcher()
        dispatcher.maxRequests = 1

        val client = OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .connectTimeout(100, TimeUnit.SECONDS)
                .dispatcher(dispatcher)
                .readTimeout(100, TimeUnit.SECONDS).build()


        client.dispatcher.cancelAll()
        val retrofit = Retrofit.Builder()
                .baseUrl(BuildConfig.API_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())
                .build()
        val api = retrofit.create(APIService::class.java)

        api.getNewToken(ReqAccessToken(cont.getSharedPreferences("app_data", 0).getString("refresh_token", "")!!)).enqueue(object : Callback<ResNewTokens> {
            override fun onResponse(call: Call<ResNewTokens>, response: retrofit2.Response<ResNewTokens>) {
                if (response.isSuccessful) {
                    val editor = cont.getSharedPreferences("app_data", 0).edit()
                    editor.putString("access_token", Objects.requireNonNull<ResNewTokens>(response.body()).access_token).apply()
                    editor.putString("refresh_token", Objects.requireNonNull<ResNewTokens>(response.body()).refresh_token).apply()
                    editor.putLong("expires_in", response.body()!!.expires_in!!).apply()

                    makeNewCall(request)
                } else {
                    when (response.code()) {
                        401 -> {
                            Singleton.logOut(cont)
                        }

                        500 -> {
                            Toast.makeText(cont, cont.getString(R.string.server_error_500), Toast.LENGTH_SHORT).show()
                        }
                    }
                }
            }

            override fun onFailure(call: Call<ResNewTokens>, t: Throwable) {

            }

        })
    }

    private fun makeNewCall(req: Interceptor.Chain): Request {
        return req.request()
                .newBuilder()
                .header("Content-type:", "application/json")
                .header("Authorization", "Bearer " + cont.getSharedPreferences("app_data", 0).getString("access_token", "")!!)
                .build()
    }
}

问题出在以下几行:

if (sp!!.getLong("expires_in", 0) - sp.getLong("time_delta", 0) - System.currentTimeMillis() / 1000 <= 60) {
            updateToken(chain)
            null
        }

我要解决的问题的本质是删除带有腐烂令牌的额外请求,该令牌肯定会返回 401 错误。为此,我将所有内容都包装在了 if 中,但无法正常实现,因为函数intercept必须以任何方式返回Response,而在这种情况下不会这样做。想使那个 null 被发送,但结果是歪曲的。您需要以某种方式取消为消息计划的请求,或者以某种方式解决此问题,但我不知道具体如何:(

更新:

以下是目前的成果:

override fun intercept(chain: Interceptor.Chain): Response {
        val sp = cont.getSharedPreferences("app_data", 0)
        val originalRequest = if (sp!!.getLong("expires_in", 0) - sp.getLong("time_delta", 0) - System.currentTimeMillis() / 1000 <= 60) {
            val interceptor = HttpLoggingInterceptor()
            interceptor.level = HttpLoggingInterceptor.Level.BODY

            val dispatcher = Dispatcher()
            dispatcher.maxRequests = 1


            val client = OkHttpClient.Builder()
                    .addInterceptor(interceptor)
                    .connectTimeout(100, TimeUnit.SECONDS)
                    .dispatcher(dispatcher)
                    .readTimeout(100, TimeUnit.SECONDS).build()


            client.dispatcher.cancelAll()
            val retrofit = Retrofit.Builder()
                    .baseUrl(BuildConfig.API_URL)
                    .client(client)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
            val api = retrofit.create(APIService::class.java)
            synchronized(this) {
                when {
                    api.getNewToken(ReqAccessToken(cont.getSharedPreferences("app_data", 0).getString("refresh_token", "")!!)).execute().isSuccessful -> {
                        val responseBody = api.getNewToken(ReqAccessToken(cont.getSharedPreferences("app_data", 0).getString("refresh_token", "")!!)).execute().body()
                        val editor = cont.getSharedPreferences("app_data", 0).edit()
                        editor.putString("access_token", Objects.requireNonNull<ResNewTokens>(responseBody).access_token).apply()
                        editor.putString("refresh_token", Objects.requireNonNull<ResNewTokens>(responseBody).refresh_token).apply()
                        editor.putLong("expires_in", responseBody!!.expires_in!!).apply()

                        chain.request()
                                .newBuilder()
                                .header("Content-type:", "application/json")
                                .header("Authorization", "Bearer " + cont.getSharedPreferences("app_data", 0).getString("access_token", "")!!)
                                .build()
                    }

                    else->{

                    }
                }
            }



        } else {
            chain.request()
                    .newBuilder()
                    .header("Content-type:", "application/json")
                    .header("Authorization", "Bearer " + cont.getSharedPreferences("app_data", 0).getString("access_token", "")!!)
                    .build()
        }


        val response = chain.proceed(originalRequest)
        when (response.code) {
            401 -> {
                //updateToken(chain)
            }
            500 -> {
                Toast.makeText(cont, cont.getString(R.string.server_error_500), Toast.LENGTH_SHORT).show()
            }
        }


        return response
    }

并val response = chain.proceed(originalRequest)说他们正在等待请求。然后我尝试在 if 中规定请求,但据我所知,它不可见。

android
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-02-16 01:18:52 +0000 UTC

在使用你的产品时如何理解用户的逻辑?

  • 2

这个问题部分是哲学性的,部分是应用的,所以不要对我评价太高:) 我认为我们大多数人已经或计划在我们的实践中发布我们自己生产的产品。这是指可以编写的所有内容,无论是某物或网站的后端,移动设备的应用程序还是桌面解决方案。由于我主要(你可以在我的问答中看到这个话题的流行)为Android做移动开发,所以我的判断会接近这个行业,但我们每个人都能理解我对这个领域的推理他的作品。

所以,让我们假设一个程序员(例如,我)正在锯他的应用程序(程序)。锯开又长又硬,在这个过程中暴露出数以万亿计的虫子和侧柱。错误被修复,拐杖被发明。现在你已经到了将你的作品发布到世界上的地步,到目前为止只用于内部测试。例如,在 Google Play 控制台中有封闭测试之类的东西。一切都已布置好,您正在等待反馈。例如,在编写程序的过程中,我连接了各种捕获错误的解决方案:一开始是这样,Fabric.io在项目顺利进行后Firebase,我连接了Firebase. 我想大多数人都知道这个服务的魅力,但是,我还是允许自己再写一遍,这个服务连接到项目,并允许您接收有关应用程序运行期间发生的错误的数据。该服务已连接,一切运行稳定。您收到错误,修复它并发布更新。如果不是为了一件事,该方案似乎是简单易懂的。在测试过程中,每个人的行为都不同,因此并不总是以相同的方式行事。而且我认为有些情况下应用程序崩溃了,你得到一个错误,但在你的测试过程中,一切都在这个位置还可以。现在实际上是问题的本质 - 如何理解用户正在做什么,应用程序正在稳步下降。毕竟程序员和用户的思维方式不同(无意冒犯用户)。是的,你可以直接行动——一个错误出现了,修复它并发布了它。但是,如果你修复了你认为正确的东西,但最终没有得到修复。当用户收到错误时如何捕捉这些条件?也许有一些解决这个问题的方法?

让我们每个人绕过错误,只有正确的代码伴随:)

android
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-02-01 21:12:41 +0000 UTC

android字符串资源中的省略号

  • 0

例如,我的应用程序中有这一行:

because ...

丁字裤看起来像这样:

<string name="because">because (…, &#8230;)</string>

在应用程序中它看起来像这样:

because (...,...)

以前,一切都在资源中显示,如下所示:

<string name="because">because ...</string>

我被要求用这样的设计替换这三个点,&#8230;因为那样会更好。结果,在替换之后,它并没有按照原来的预期显示。也许我替换了错误的东西或者是一个小故障,你不应该将省略号更改为建议的选项?

android
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-01-30 17:54:09 +0000 UTC

NestedScrollView 在自己的 android 上滚动

  • 0

有这个标记:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".pollsModule.PollsScr">


    <View
        android:id="@+id/divider"
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:layout_marginTop="3dp"
        android:background="@color/colorAccent" />


    <TextView
        android:id="@+id/intro_text_header"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginTop="15dp"
        android:layout_marginEnd="10dp"
        android:textAlignment="center"
        android:visibility="gone" />

    <TextView
        android:id="@+id/intro_text_body"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/intro_text_header"
        android:layout_marginStart="10dp"
        android:layout_marginTop="10dp"
        android:layout_marginEnd="10dp"
        android:visibility="gone" />

    <Button
        android:id="@+id/next"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginStart="10dp"
        android:layout_marginEnd="10dp"
        android:layout_marginBottom="10dp"
        android:background="@drawable/main_screen_btn"
        android:visibility="gone" />


    <androidx.core.widget.NestedScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:overScrollMode="never"
        android:layout_below="@id/divider">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:id="@+id/question_text"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"
                android:layout_marginStart="10dp"
                android:layout_marginTop="15dp"
                android:layout_marginEnd="10dp"
                android:layout_marginBottom="10dp"
                android:fontFamily="@font/opensans_semibold"
                android:textColor="#666666"
                android:visibility="gone"
                app:autoSizeMaxTextSize="18sp"
                app:autoSizeMinTextSize="14sp"
                app:autoSizeStepGranularity="1sp"
                app:autoSizeTextType="uniform" />

            <EditText
                android:id="@+id/user_input"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/question_text"
                android:layout_marginStart="10dp"
                android:layout_marginTop="15dp"
                android:layout_marginEnd="10dp"
                android:layout_marginBottom="10dp"
                android:fontFamily="@font/opensans_semibold"
                android:textColor="#666666"
                android:visibility="gone" />

            <ImageView
                android:id="@+id/questionImg"
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:layout_alignParentTop="true"
                android:layout_centerHorizontal="true"
                android:contentDescription="QuestionImg"
                android:visibility="gone" />


            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/answerOptions"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/user_input"
                android:layout_marginStart="5dp"
                android:layout_marginTop="2dp"
                android:layout_marginEnd="5dp"
                android:layout_marginBottom="10dp"
                android:overScrollMode="never"
                android:visibility="gone"
                app:layout_behavior="@string/appbar_scrolling_view_behavior" />

            <LinearLayout
                android:id="@+id/question_buttons"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/answerOptions"
                android:orientation="horizontal"
                android:visibility="gone"
                android:weightSum="20">

                <Button
                    android:id="@+id/prev_question"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_marginEnd="10dp"
                    android:layout_marginBottom="10dp"
                    android:layout_weight="10"
                    android:text="@string/previous_question_polls" />

                <Button
                    android:id="@+id/next_question"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_marginStart="10dp"
                    android:layout_marginEnd="10dp"
                    android:layout_marginBottom="10dp"
                    android:layout_weight="10"
                    android:background="@drawable/main_screen_btn"
                    android:text="@string/next_question_polls"
                    android:visibility="gone" />

            </LinearLayout>
        </RelativeLayout>

    </androidx.core.widget.NestedScrollView>
</RelativeLayout>

并且有一个这样的列表:

 <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/answerOptions"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/user_input"
                android:layout_marginStart="5dp"
                android:layout_marginTop="2dp"
                android:layout_marginEnd="5dp"
                android:layout_marginBottom="10dp"
                android:overScrollMode="never"
                android:visibility="gone"
                app:layout_behavior="@string/appbar_scrolling_view_behavior" />

在此列表中,在某些条件下,元素可以具有以下标记:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/question_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginTop="15dp"
        android:layout_marginEnd="10dp"
        android:layout_marginBottom="10dp"
        android:textColor="#666666"
        app:autoSizeMaxTextSize="16sp"
        app:autoSizeMinTextSize="12sp"
        app:autoSizeStepGranularity="1sp"
        app:autoSizeTextType="uniform" />


    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/answerOptions"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/question_text"
        android:layout_marginStart="5dp"
        android:layout_marginTop="2dp"
        android:layout_marginEnd="5dp"
        android:layout_marginBottom="10dp"
        android:overScrollMode="never"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</RelativeLayout>

简单来说,一个list里面会有几个list:

NestedScrollView
- RecyclerView_1
-- LinearLayout
--- RecyclerView_2

我不确定我描绘的是否正确,但我试图把它描绘清楚))问题的本质:例如,列表中有RecyclerView_13 个元素,3 个列表中的每一个RecyclerView_2都有 6 个元素。例如,如果我们单击位于我RecyclerView_2的位置 2的元素之一或滚动到最顶部。我无法弄清楚可能是什么问题。我想制作 smoothScrollTo 但它没有帮助。RecyclerView_1NestedScrollViewRecyclerView_1

android
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-01-25 19:26:38 +0000 UTC

如何获取android 10的存储路径?

  • 4

之前的路径是这样的:

root = File(Environment.getExternalStorageDirectory().absolutePath)

但是在 android 10 发布后,这个东西就被弃用了。在网上找到了这个:

String destPath = mContext.getExternalFilesDir(null).getAbsolutePath();

或像这样:

val externalStorageVolumes: Array<out File> =
                ContextCompat.getExternalFilesDirs(applicationContext, null)
val primaryExternalStorage = externalStorageVolumes[0]

但他们都返回这个:

/storage/emulated/0/Android/data/com.example.my/files

我需要:

/storage/emulated/0/

我看到两个选项:

  1. 切断路径中不必要的部分,最终得到/storage/emulated/0/
  2. 立即对根进行硬编码,而不是通过函数获取它。

也许这个问题还有其他解决方案?

android
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-01-24 19:32:51 +0000 UTC

动态移除bottomNavigationView菜单项

  • 0

当条件满足时,我试图在活动中以编程方式从菜单中删除一些项目。我这样做:

if (!sp!!.getStringSet("disabled_app_modules", HashSet<String>()).isNullOrEmpty()) {
 val set = sp!!.getStringSet("disabled_app_modules", HashSet<String>())
 when {
   set.contains("notepad") -> {
     bottomNavigationView.menu.removeItem(R.id.notespec)
   }
 }
}

但没有什么是这样的。如果在小部件声明后直接删除元素,那么一切正常:

bottomNavigationView.menu.removeItem(R.id.notespec)

想这样做:

bottomNavigationView.postInvalidate()

但没有帮助。我认为问题是一个空集来了,但是内存中有一个集并且它不是空的。问题出在以下几行:

set.contains("notepad") -> {
     bottomNavigationView.menu.removeItem(R.id.notespec)
   }

但是这里不知道哪里可能有问题,一切似乎都写对了,还是不...

更新

有一个假设为什么没有找到这些元素,但在我看来这不是很合理。这是我的一套:

<set name="disabled_app_modules">
   <string>&quot;notepad&quot;</string>
</set>

我正在寻找set.contains("notepad")也许我仍然需要以某种方式考虑括号还是胡说八道?

android
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-01-22 17:21:58 +0000 UTC

从 ArrayList kotlin 中删除元素

  • 0

我正在尝试从列表中删除一个元素。但是,我设置的索引是这样的:

answerIds.indexOf(finishedTasksGroups[i])

一般结构是:

for (i in 1 until finishedTasksGroups.size) {
answersTxts.removeAt(answerIds.indexOf(finishedTasksGroups[i]))
}

但结果,它没有按应有的方式被删除。在finishedTasksGroups我有 3 个元素中,在answersTxts5中。finishedTasksGroups 它看起来像这样:[1,2,3]最后answersTxts,应该显示 4 和 5 个元素,但显示了 1,3 和 5。我不明白我做错了什么,一切似乎写得正确,但是因为在某个地方一定有错误。

kotlin
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-01-14 16:27:36 +0000 UTC

将 JsonArray 转换为 ArrayList<MyModel> kotlin android 的方法

  • 0

我从服务器接收数据,结果,根据我收到的数据,我制作了 JsonArray。但我需要以某种方式将此 JsonArray 转换为常规的类对象数组。当然,有一些方法可以根据原理运行 - 我从一个数组中取出并将其添加到另一个数组中,大致如下所示:

List<MyObj> list = new ArrayList<>();
if (outputs!= null) { 
  int len = outputs.length();
  for (int i=0; i<len; i++) { 
    JSONObject o = (JSONObject) outputs.get(i);
    list.add(new MyObj(o.getString('name'), o.getString('URL')));
  } 
} 

这里当然是用的,但是JSONObject我JsonObject用的,不过我觉得不会有太大的区别。我目前正在尝试这样做:

val testArray = tpsObject.getAsJsonObject("questions")[tpsSelection[0].toString()].asJsonArray
  for (i in 0 until testArray.size()) {
Log.i("m",Gson().fromJson(testArray.get(i).asJsonObject.toString(),QuestionModel::class.java).question.toString())
   }

但我收到一个错误:

 com.google.gson.JsonSyntaxException: Expected a com.google.gson.JsonObject but was com.google.gson.JsonArray

当我只是尝试输出一个数组时:

Log.i("m",testArray.get(i).asJsonObject.toString())

然后一切都正常显示在日志中,它仍然只是以某种方式转换为所需的。像这样尝试:

val jsonParser = JsonParser.parseString(testArray.get(i).asJsonObject.toString())
val model: QuestionModel = Gson().fromJson(jsonParser, QuestionModel::class.java)

我得到与上面相同的错误。完成此任务的选项有哪些?

android
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-12-31 01:11:12 +0000 UTC

安装manjaro linux时遇到问题

  • 2

前段时间我在这里问了一个关于切换到 Linux 的问题。我想尝试坐在这个系统上作为主要的,它作为win10的替代品。我想立即要求您不要为“背叛”投反对票。总的来说,我喜欢 Windows,我觉得它很舒服,但最近我想要一些在设计方面更简单、在内部结构方面更强大的东西。由于 makos 在默认情况下价格昂贵,因此选择落在了 Linux 上。起初我不想打扰并切换到 bubuntu,因为我认为它是最受欢迎的发行版。进一步谷歌搜索并研究这个问题,我遇到了 Linux Manjaro KDE。我不知道我是否做出了正确的选择,所以如果有人有建议或好的建议,如果你写在评论中,我将不胜感激。我为 android 编写应用程序(从我的问题的主题中可以看出),因此,我也非常担心继续在 Linux 上工作的可能性。但似乎(据我所知)manjaro 与其他发行版一样,通常会提取所需的一切。如果有人有从 Windows 切换到 Linux 的经验,那么我将不胜感激。

现在问题的本质:既然我决定拆除Windows,安装Linux作为主系统,我需要创建一个可启动的U盘进行安装。我拿了一个 32GB 的闪存驱动器(也许更少,我不知道),并首先使用 rufus 写下了所有内容。系统没有启动。然后我使用了ultraiso程序——系统没有启动。当我尝试启动时出现错误:

grub unknown file system

此外,还可以只输入一个命令。正如我从论坛中了解到的那样,问题出在 grub 版本中。但我不太明白如何解决这个问题。其实有两个问题:

  1. 要不要麻烦,把这个系统作为主要系统,如果是,如何解决这个问题。
  2. 您对所选发行版有何看法,它真的和他们在网上写的一样好,还是有更好的?

在切换到另一个轴方面我是新手,所以不要太严厉地判断:)

更新

先生们 linuksovedy 现在可能会踢我一点。我们通常有一个知识库,因此在这里我想附上我遇到的这个错误的解决方案。最重要的是,在将 Linux(无论如何我理解)写入 USB 闪存驱动器时,会弹出此窗口:

在此处输入图像描述

并且您需要准确选择DD记录方法。我选择了它,刻录了闪存驱动器,一切正常。谁在乎什么电脑。也许我的回答对某人有用。在这个论坛上找到了解决方案。

linux
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-12-25 19:03:53 +0000 UTC

在 android 测验中导航时出错

  • 1

我正在应用程序中做一个测验问卷。有前进和后退两个按钮。我展示了一系列问题。先决条件是能够显示最后 5 个已回答的问题。所有问题(包括已回答的问题)、所有答案(如果有)都来自服务器。收到所有内容后,我过滤未回答的问题并将它们添加到数组中。我还将最后 5 个问题的答案放在一个单独的数组中。现在它的工作原理是这样的——在接收、过滤之后,我显示第一个未回答的问题,而显示上一个问题的按钮处于活动状态,而显示下一个问题的按钮处于非活动状态(还没有答案)。我现在可以单击返回查看 5 个已回答的问题及其答案选项。我可以从数组的开头走到结尾,然后后退按钮变为非活动状态,直到按下前进按钮。问题的本质是,只有当我使用后退按钮转到最后一个回答的问题时,我才能正常浏览问题,例如,如果我想查看第一个回答的问题,然后返回第一个未回答的问题,然后我将不得不单击“转发”按钮两次。下面是处理按钮点击的代码:

updateAdapter(0, questionsIndex, answersOptions, 1, ArrayList<Int>())
questionsIndex += 1

next_question.setOnClickListener {
 if (questionsIndex != questionType1.lastIndex) {
 if (userAnswerId != null) {
   Singleton.apiService().sendAnswer("Bearer " + context!!.getSharedPreferences("app_data", 0).getString("access_token", "")!!, OutAnswerModel(questionType1[questionsIndex - 1].id!!, userAnswerId!!))
  .enqueue(object : Callback<OutAnswerModel> {
  override fun onResponse(call: Call<OutAnswerModel>, response: Response<OutAnswerModel>) {
 if (response.isSuccessful) {
  lastAnswersArray.add(0, questionType1[questionsIndex - 1])
  userAnswers.add(0, userAnswerId!!)
  userAnswerId = null
  userAnswers.removeAt(userAnswers.lastIndex)
  lastAnswersArray.removeAt(lastAnswersArray.lastIndex)

  updateAdapter(0, questionsIndex, answersOptions, 1, ArrayList<Int>())
  questionsIndex += 1
 }
  }


   override fun onFailure(call: Call<OutAnswerModel>, t: Throwable) {

}
})
} else if (answerIndex in -1..4) {
when {
answerIndex >= 0 -> {
updateAdapter(1, answerIndex, answersOptions, 2, userAnswers[answerIndex])
}
answerIndex < 0 -> {
answerIndex = 0
updateAdapter(0, questionsIndex - 1, answersOptions, 1, ArrayList<Int>())
}
}
answerIndex -= 1
prev_question.isEnabled = true
}

} else {
workingWithViews(1)

textSetter(finalText!![0], finalText[1], finalText[2])
next.isEnabled = false
Handler().postDelayed({
next.isEnabled = true
}, 1000)
}

}

if (lastAnswersArray.isNotEmpty()) {
prev_question.setOnClickListener {
updateAdapter(1, answerIndex, answersOptions, 2, userAnswers[answerIndex])

if (answerIndex != lastAnswersArray.lastIndex) {
answerIndex += 1
} else {
prev_question.isEnabled = false
}
}
} else {
answerIndex -= 1
prev_question.isEnabled = false


 }

我的算法很可能在某个地方失败了,但我无法确切知道在哪里以及如何修复它。它似乎考虑了一切,但它并没有按应有的方式工作。也许解释不是很清楚,所以如果有人不明白,请询问。

UPD

算法的问题似乎可以定位。当我点击后退按钮时,我将响应索引增加 1:

if (answerIndex != lastAnswersArray.lastIndex) {
answerIndex += 1 // тут 
} else {
prev_question.isEnabled = false
}

然后我按下“前进”按钮并将索引减 1:

else if (answerIndex in -1..4) {
answerIndex -= 1 // тут 
when {
answerIndex >= 0 -> {
updateAdapter(1, answerIndex, answersOptions, 2, userAnswers[answerIndex])
}
answerIndex < 0 -> {
answerIndex = 0
updateAdapter(0, questionsIndex - 1, answersOptions, 1, ArrayList<Int>())
}}
prev_question.isEnabled = true
}

事实证明,当我们点击“后退”时,我们增加了索引,当我们点击“前进”时,我们减少了它,结果,我们需要按下它两次,以便索引减少到足以触发条件。还没想好怎么解决:(

android
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-12-15 23:28:07 +0000 UTC

从 Windows 10 切换到 Linux Ubuntu - 有哪些陷阱?

  • 1

有一种情况是,我在这个问题上的消息来源太多,我无法完全决定。最重要的是 - 现在我的笔记本电脑上安装了 Windows 10 Pro,几乎从它刚推出的那一刻起我就一直在使用它。但现在我想知道 - 也许值得切换到 ubuntu。我是一名专业的Android开发人员,或者感兴趣的领域,因为这对任何人来说都会更方便。我所有的都是一个 IDE 模拟器和一个浏览器。也就是说,轴在开发过程中几乎没有任何作用。我尝试在一台第三方 PC 上在 ubuntu 下工作,老实说,我没有遇到任何问题。也就是说,当然,存在差异和其他一切,但我对与过渡相关的可能问题感兴趣(除了整个操作系统的功能)。比如——我有一个windows上的office,当然ubuntu上有一个libre office,但是离微软很远,因此,如果我使用 google docks 或 office 365,其他一切,如模拟器或 IDE,都与 Windows 上的工作方式相同。Windows 的问题在于,您需要做很多事情才能使一切顺利而美观地运行 - 很多东西都需要写入注册表和其他地方。我也对一个相当尖锐的问题感兴趣——如何处理驱动程序,因为在 Windows 下一切都很简单,我下载了文件并安装了它,一切都很漂亮,但是例如在 ubuntu 上该怎么办?在这种情况下您能提供什么建议,否则我会进退两难))希望您提供有用的建议 :) 毕竟,在 Windows 下一切都很简单,我下载了文件并安装了它,一切都很漂亮,但是在 ubuntu 上做什么呢?在这种情况下您能提供什么建议,否则我会进退两难))希望您提供有用的建议 :) 毕竟,在 Windows 下一切都很简单,我下载了文件并安装了它,一切都很漂亮,但是在 ubuntu 上做什么呢?在这种情况下您能提供什么建议,否则我会进退两难))希望您提供有用的建议 :)

linux
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-11-29 20:09:10 +0000 UTC

无法在 Android Studio 中为某些字符串添加翻译

  • 1

我想通过翻译编辑器将翻译添加到另一种语言。所以事实证明,工作室并不想接受他们:

在此处输入图像描述

我重新启动了工作室,重建了项目,删除并添加了这个语言环境,但由于某种原因,这些行不想被翻译。也就是说,我可以输入,但表格中什么都没有,如果你在一个单元格中输入了多次翻译,那么它就会出现在strings.xml文件中,例如:

<string name="job_type_fulltime">A tiempo completo</string>
<string name="data_loading_subtitle">A tiempo completo</string>
<string name="data_loading_title">A tiempo completo</string>
<string name="job_type_full_part_time">A tiempo completo</string>
<string name="job_type_fulltime">A tiempo completo</string>
<string name="job_type_parttime">A tiempo completo</string>
<string name="job_type_full_part_time">A tiempo completo</string>
<string name="data_loading_title">A tiempo completo</string>
<string name="job_type_full_part_time">A tiempo completo</string>
<string name="job_type_fulltime">A tiempo completo</string>
<string name="job_type_parttime">A tiempo completo</string>
<string name="data_loading_title">A tiempo completo</string>
<string name="data_loading_subtitle">1</string>
<string name="data_loading_subtitle">1</string>

我不知道出了什么问题以及如何解决它。也许他选择了错误的语言环境或在其他地方钝化了它?

android
  • 1 个回答
  • 10 Views
Martin Hope
Andrew
Asked: 2020-10-19 01:40:18 +0000 UTC

致命例外:ControllerMessenger - 如何解决安卓问题?

  • 0

在 Google Play Console 中,经过另一次测试,出现了这种类型的错误:

FATAL EXCEPTION: ControllerMessenger
Process: de.jobnetzwerk.jobnet, PID: 14483
kotlin.KotlinNullPointerException
    at de.jobnetzwerk.jobnet.notepad.NoteData.clearAdapter(NoteData.kt:274)
    at de.jobnetzwerk.jobnet.notepad.NoteData.access$clearAdapter(NoteData.kt:26)
    at de.jobnetzwerk.jobnet.notepad.NoteData$getRemarksList$1.onResponse(NoteData.kt:284)
    at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:71)
    at android.os.Handler.handleCallback(Handler.java:746)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at androidx.test.espresso.base.Interrogator.a(Interrogator.java:19)
    at androidx.test.espresso.base.UiControllerImpl.a(UiControllerImpl.java:169)
    at androidx.test.espresso.base.UiControllerImpl.a(UiControllerImpl.java:161)
    at androidx.test.espresso.base.UiControllerImpl.a(UiControllerImpl.java:141)
    at androidx.test.espresso.action.Tap$1.a(Tap.java:6)
    at androidx.test.espresso.action.GeneralClickAction.perform(GeneralClickAction.java:20)
    at androidx.test.espresso.ViewInteraction$SingleExecutionViewAction.perform(ViewInteraction.java:9)
    at androidx.test.espresso.ViewInteraction.a(ViewInteraction.java:79)
    at androidx.test.espresso.ViewInteraction.a(ViewInteraction.java:97)
    at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:3)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    at android.os.Handler.handleCallback(Handler.java:746)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5459)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)

并且在 12 台设备中有 6 台发现了这样的错误。我看到了这个问题,它是关于某种误报的。问题是谷歌在完全陌生的地方发现错误。我并不是说我的应用程序是完美的,他们只是进入了这样的丛林并发现了有时与应用程序完全无关的错误。如何解决此错误?

更新

错误行:

at de.jobnetzwerk.jobnet.notepad.NoteData.clearAdapter(NoteData.kt:274)

代码片段:

override fun onResume() {
    super.onResume()
    dialog!!.setOnKeyListener { _, code, event ->
        if (code == KeyEvent.KEYCODE_BACK) {
            if (event.action == KeyEvent.ACTION_DOWN) {
                webView.clearHistory()
                dialog!!.dismiss() // строка 274
                true
            } else {

                true
            }
        } else {
            false
        }
    }
}
android
  • 1 个回答
  • 10 Views

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    我看不懂措辞

    • 1 个回答
  • Marko Smith

    请求的模块“del”不提供名为“default”的导出

    • 3 个回答
  • Marko Smith

    "!+tab" 在 HTML 的 vs 代码中不起作用

    • 5 个回答
  • Marko Smith

    我正在尝试解决“猜词”的问题。Python

    • 2 个回答
  • Marko Smith

    可以使用哪些命令将当前指针移动到指定的提交而不更改工作目录中的文件?

    • 1 个回答
  • Marko Smith

    Python解析野莓

    • 1 个回答
  • Marko Smith

    问题:“警告:检查最新版本的 pip 时出错。”

    • 2 个回答
  • Marko Smith

    帮助编写一个用值填充变量的循环。解决这个问题

    • 2 个回答
  • Marko Smith

    尽管依赖数组为空,但在渲染上调用了 2 次 useEffect

    • 2 个回答
  • Marko Smith

    数据不通过 Telegram.WebApp.sendData 发送

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5