Android Studio: наиболее эффективный способ извлечения огромных текстовых данных и последующего отображения в Activity - PullRequest
0 голосов
/ 01 мая 2020

Какой самый эффективный способ получения данных и отображения в действии. Раньше я выбирал текстовые элементы, используя

<string-array name="data">
  <item>
     Hii how are you? 
     .
     . +
     1000 lines of words
  </item>

Спасибо

1 Ответ

0 голосов
/ 02 мая 2020

У вас есть XML ресурс массива строк, который содержит огромные строки. Как насчет того, чтобы хранить ваши огромные текстовые данные в отдельных файлах в каталоге assets, и, возможно, хранить имена файлов в ресурсе строкового массива. Затем по имени файла вы можете открыть и загрузить текстовые данные из файла активов.

Здесь я предлагаю способ эффективной загрузки огромных текстовых данных и отображения их в Activity.

Я использую поток для чтения огромных текстовых файлов в фоновом режиме.

Поток использует BufferedReader для чтения большого потока данных из файла. BufferedReader буферизует символы из потока данных, чтобы обеспечить эффективное чтение символов, массивов и строк.

В приведенном ниже примере поток использует BufferedReader для чтения текстовых данных построчно. Он читает текст за строкой и отправляет их в Activity через обработчик.

Это класс Kotlin, представляющий строку текста. Он содержит текстовую строку и номер строки.

TextLine.kt

class TextLine(
    val lineNumber: Int,
    val textLine: String
)

Это класс Thread, который читает текст построчно.

TextReaderThread.kt

class TextReaderThread(private val mInputStream: InputStream,
                       private val mTextLineHandler: Handler) : Thread() {

    private val mStopped = AtomicBoolean(false)

    override fun run() {
        mStopped.set(false)

        val bufferedReader = BufferedReader(InputStreamReader(mInputStream))

        // Read first line
        var lineNumber = 1
        var textLine: String? = bufferedReader.readLine()

        while (null != textLine) {
            // Send read line to MainActivity
            Message.obtain(mTextLineHandler, 0, TextLine(lineNumber, textLine)).sendToTarget()

            // Check if thread is interrupted and stopped
            if(mStopped.get()) break

            // Read next line
            textLine = bufferedReader.readLine()
            lineNumber++
        }
    }

    override fun interrupt() {
        super.interrupt()
        // Thread is interrupted to stop
        mStopped.set(true)
    }

}

Для отображения данных в режиме прокрутки я использую RecyclerView в Activity.

RecyclerView может эффективно обрабатывать и отображать большое количество данных при прокрутке данных пользователем.

Это макет одной строки данных, которая будет заполнена в RecyclerView. Слева TextView отображает номер строки, а справа TextView отображает строку текста.

list_item. xml

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/lineNumber"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintHorizontal_weight="1"
        android:textSize="11sp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/textLine" />

    <TextView
        android:id="@+id/textLine"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintHorizontal_weight="9"
        android:textSize="12sp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toEndOf="@id/lineNumber"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Это классы Adapter и ViewHolder для RecyclerView.

TextLineAdapter.kt

class TextLineAdapter(private val mContext: Context) : RecyclerView.Adapter<ViewHolder>() {

    private val mItems = mutableListOf<TextLine>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false)
        )
    }

    override fun getItemCount() = mItems.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.lineNumber.text = mItems[position].lineNumber.toString()
        holder.textLine.text = mItems[position].textLine
    }

    fun addTextLine(textLine: TextLine) {
        // Add new item to the end of list
        mItems.add(textLine)
        // Notify that an item is added to end of the list
        notifyItemInserted(mItems.size - 1)
    }

    fun clear() {
        // Clear item list
        mItems.clear()
        // Notify that full data set has been changed
        notifyDataSetChanged()
    }

}

class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    val lineNumber = view.lineNumber
    val textLine = view.textLine
}

Это макет действия.

Activity_main. xml

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Это класс деятельности.

MainActivity.kt

class MainActivity : AppCompatActivity() {

    private lateinit var mTextLineHandler: Handler

    private lateinit var mTextReaderThread: Thread

    private lateinit var mTextLineAdapter: TextLineAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // Create Handler which uses main looper, to handle messages from TextReaderThread
        mTextLineHandler = object : Handler(mainLooper) {
            override fun handleMessage(msg: Message) {
                // Add text line received from TextReaderThread to recycler view
                mTextLineAdapter.addTextLine(msg.obj as TextLine)
            }
        }

        // Set layout manager and adapter of recycler view
        recyclerView.layoutManager = LinearLayoutManager(baseContext)
        mTextLineAdapter = TextLineAdapter(baseContext)
        recyclerView.adapter = mTextLineAdapter
    }

    override fun onResume() {
        super.onResume()
        // Clear recycler view
        mTextLineAdapter.clear()

        // Create TextReaderThread to read text lines from assets/alice29.txt file.
        // Text lines read by TextReaderThread will be received and handled by mTextLineHandler.
        mTextReaderThread = TextReaderThread(assets.open("alice29.txt"), mTextLineHandler)
        // Start TextReaderThread
        mTextReaderThread.start()
    }

    override fun onPause() {
        super.onPause()
        // Interrupt TextReaderThread to stop
        mTextReaderThread.interrupt()
        // Wait until TextReaderThread stops
        mTextReaderThread.join()
    }

}

В этом примере я использую только один большой текстовый файл с именем alice29.txt. Я загрузил файл alice29.txt из http://corpus.canterbury.ac.nz/descriptions/

В этом примере приложения считывается только один огромный текстовый файл (alice29.txt) и загружается содержимое в RecyclerView, как показано на следующих снимках экрана.

Верхняя часть RecyclerView.

enter image description here

Прокрутка до нижней части RecyclerView.

enter image description here

RecyclerView содержит 3609 строк текста.

...