Странный RecyclerView лаг во фрагменте - PullRequest
1 голос
/ 28 апреля 2020

Я сталкиваюсь со странной задержкой RecyclerView в моем фрагменте после асинхронной задачи c. Он останавливается на несколько миллисекунд, прежде чем мой веб-запрос будет завершен. Я чувствую, что проблема может быть связана с некоторой блокировкой потока пользовательского интерфейса, но я не могу понять, что нужно изменить в моем коде, чтобы заставить его работать. Следующий код отлично работает внутри Activity , я получил эту проблему, только когда использую его внутри своего фрагмента.

Вот мой фрагмент:

class MyFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        super.onCreateView(inflater, container, savedInstanceState)
        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.my_fragment, container, false)
        setup(view)
        return view
    }

    private fun setup(view: View) {
        val myAdapter = MyAdapter(
            SharedData.dataViewModel,
            object :
                MyAdapter.Callback {
                //...
            })
        view.recyclerView.adapter = myAdapter
        val layoutManager: RecyclerView.LayoutManager = LinearLayoutManager(activity)
        view.recyclerView.layoutManager = layoutManager

        view.progressBarLayout.visibility = View.VISIBLE
        SharedData.dataViewModel.retrieve { success, error ->
            view.progressBarLayout.visibility = View.INVISIBLE
            if (success) {
                view.recyclerView.adapter?.notifyDataSetChanged()
            } else {
                error?.let {
                    Toast.makeText(
                        requireContext(), it.localizedMessage,
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }
        }
    }
}

Внутри retrieve метод, который я получил:

Webservice.shared.getData()
    .observeOn(AndroidSchedulers.mainThread())
    .subscribeOn(Schedulers.io())
    .subscribe ({ result ->
        //...
    }, { error ->
        //...    
    })

И getData - это простой GET запрос на модификацию2:

@GET("get_data")
    fun getData(): Observable<DataModelResult>

Редактировать

Вот мой xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:background="@android:color/white"
    android:orientation="vertical"
    tools:context=".screens.sample.fragment.MyFragment">

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingLeft="@dimen/_14sdp"
            android:paddingRight="@dimen/_14sdp"
            android:layout_marginTop="@dimen/_10sdp"
            android:layout_marginBottom="@dimen/_10sdp">
            <TextView
                android:id="@+id/topTextView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/sample_text"
                android:lineSpacingMultiplier="1.2"
                android:textColor="@android:color/black"
                android:textSize="@dimen/_17ssp"
                android:gravity="center_horizontal" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingLeft="@dimen/_14sdp"
            android:paddingRight="@dimen/_14sdp"
            android:weightSum="1">

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/recyclerView"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
                tools:listitem="@layout/item_layout_child"
                android:layout_weight="1"/>

            <Button
                android:id="@+id/nextButton"
                android:layout_width="match_parent"
                android:layout_height="55dp"
                android:background="@drawable/button_rounded"
                android:backgroundTint="@color/CustomColor"
                android:layout_marginLeft="32dp"
                android:layout_marginRight="32dp"
                android:layout_marginTop="14dp"
                android:layout_marginBottom="22dp"
                android:textAllCaps="true"
                android:textColor="@drawable/button_text_color"
                android:textSize="@dimen/_16ssp"
                style="?android:attr/borderlessButtonStyle"
                android:elevation="5dp"
                android:translationZ="1dp" />
        </LinearLayout>

    </LinearLayout>

    <include
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        layout="@layout/indicator_layout" />

</FrameLayout>

Ответы [ 3 ]

0 голосов
/ 28 апреля 2020

В вашей ситуации это зависит от того, что вы делаете в обратном вызове success из вашего метода получения. Поскольку вы наблюдаете этот обратный вызов в AndroidSchedulers.mainThread(), если вы выполняете какие-то тяжелые вычисления или сохраняете данные локально и т. Д. c, это может создать тот лаг, о котором вы говорите. Попробуйте понаблюдать и, возможно, проанализировать результат в фоновом потоке и обновить только интерфейс в основном потоке.

0 голосов
/ 29 апреля 2020

Наконец, я думаю, что выяснил, что стало причиной этой проблемы в моем случае. Я настроил некоторые анимации внутри своего навигационного графика и, скорее всего, они вызывали какую-то блокировку потока. Размещение кода в фоновом потоке не помогло мне вообще. Таким образом, в этом случае я предложил 2 возможных решения:

  1. Программная настройка анимации (К сожалению, я не нашел способа добавить слушателя к моей xml анимации ) и добавьте слушателей. После этого вы можете легко приступить к выполнению задания asyn c после завершения анимации перехода. Пример: { ссылка }

  2. Если у вас много разных анимаций или вы хотите запустить задачу asyn c до окончания анимации, вы также можете положить свой completion возврат внутрь некоторого Handler(). Это решение, конечно, не самое лучшее и может вызвать некоторые проблемы в будущем, но если вам нужно просто быстрое решение, вы можете попробовать его.

Handler().postDelayed({
    completion(true, null)
}, context.resources.getInteger(R.integer.fragment_animation_length).toLong())
0 голосов
/ 28 апреля 2020

Попробуйте запустить представление (в данном случае вызывая setup) из-за перегрузки метода onViewCreated вместо метода onCreateView. Надеюсь, это разрешит отставание.

...