活动开始非常缓慢,因为RecyclerView图片

时间:2019-02-14 22:54:16

标签: android performance kotlin android-recyclerview recycler-adapter

我有一个活动,该活动的RecyclerView中包含 28张图像,负责将所有图像addRecordImages()添加到RecyclerView适配器的方法是Activity起步很慢(超过1秒),我该怎么办才能解决此问题?如果我在方法中添加注释行,则开始时间会缩短为 500-550ms

以下是代码:

import android.app.Activity
import android.app.DatePickerDialog
import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.GridLayoutManager
import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.Spinner
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_add_edit_record.*
import kotlinx.android.synthetic.main.content_add_edit_record.*
import java.text.DecimalFormat
import java.text.SimpleDateFormat
import java.util.*

const val RECORD_ID = "RECORD_ID"
const val RECORD_CATEGORY = "RECORD_CATEGORY"
const val RECORD_AMOUNT = "RECORD_AMOUNT"
const val RECORD_DATE = "RECORD_DATE"
const val RECORD_DESCRIPTION = "RECORD_DESCRIPTION"
const val RECORD_IMAGE = "RECORD_IMAGE"
const val RECORD_IMAGE_DESCRIPTION = "RECORD_IMAGE_DESCRIPTION"
var RECORD_DATE_VALUE: String? = null
var CATEGORY_SPINNER_VALUE: String? = null

class AddEditRecordActivity : AppCompatActivity(), 
AdapterView.OnItemSelectedListener {

var recordImages = ArrayList<RecordImageAndDescription>()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_add_edit_record)
    setSupportActionBar(toolbar)

    supportActionBar?.setDisplayHomeAsUpEnabled(true)

    val spinner: Spinner = findViewById(R.id.category_spinner)

    val spinnerAdapter: ArrayAdapter<CharSequence> =
        ArrayAdapter.createFromResource(this, R.array.category_list, android.R.layout.simple_spinner_item)

    spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
    spinner.adapter = spinnerAdapter
    spinner.onItemSelectedListener = this

    val calculatorButtonListener = View.OnClickListener {
        val intent = Intent(this, CalculatorActivity::class.java)
        startActivity(intent)
    }

    val buttonSaveRecordListener = View.OnClickListener {
        saveRecord()
    }

    button_save_record.setOnClickListener(buttonSaveRecordListener)

    calculator_button.setOnClickListener(calculatorButtonListener)

    val locale = Locale.getDefault().toString()

    val calendar = Calendar.getInstance()

    val year = calendar.get(Calendar.YEAR)

    val month = calendar.get(Calendar.MONTH)

    val day = calendar.get(Calendar.DAY_OF_MONTH)


    val datePickerListener =
        DatePickerDialog.OnDateSetListener { view, selectedYear, selectedMonth, selectedDayOfMonth ->

            var selectedMonthFormated: Any? = null

            var selectedDayFormated: Any? = null

            if (selectedMonth < 10) {

                selectedMonthFormated = String.format("%02d", selectedMonth + 1)
            } else {
                selectedMonthFormated = selectedMonth + 1
            }

            if (selectedDayOfMonth < 10) {

                selectedDayFormated = "0" + selectedDayOfMonth
            } else {
                selectedDayFormated = selectedDayOfMonth.toString()
            }

            RECORD_DATE_VALUE = selectedYear.toString() + "-" + selectedMonthFormated + "-" + selectedDayFormated

            if (locale == "en_US") {
                date_text.setText(selectedYear.toString() + "-" + selectedMonthFormated + "-" + selectedDayFormated)
            } else {
                date_text.setText(selectedDayFormated + "-" + selectedMonthFormated + "-" + selectedYear)
            }
        }

    val calendarButtonListener = View.OnClickListener {
        val datePicker = DatePickerDialog(this, datePickerListener, year, month, day)

        datePicker.show()
    }

    calendar_button.setOnClickListener(calendarButtonListener)

    val intent = intent

    if (intent.hasExtra(RECORD_ID)) {
        setTitle(R.string.title_activity_edit_record)

        RECORD_DATE_VALUE = intent.getStringExtra(RECORD_DATE)

        val spinnerItemPosition = spinnerAdapter.getPosition(intent.getStringExtra(RECORD_CATEGORY))

        spinner.setSelection(spinnerItemPosition)

        amount_input.setText(intent.getStringExtra(RECORD_AMOUNT))

        val parser = SimpleDateFormat("yyyy-MM-dd")

        val formater = SimpleDateFormat("dd-MM-yyyy")

        val formatedDate = formater.format(parser.parse(intent.getStringExtra(RECORD_DATE))).toString()

        date_text.setText(if (locale == "en_US") intent.getStringExtra(RECORD_DATE) else formatedDate)

        description_input.setText(intent.getStringExtra(RECORD_DESCRIPTION))

    } else {
        setTitle(R.string.title_activity_add_record)
    }

    record_image_list.layoutManager = GridLayoutManager(this, 3)

    record_image_list.adapter = AddEditRecordAdapter(this, recordImages)
    record_image_list.setHasFixedSize(true)

    addRecordImages()
}

override fun onResume() {
    super.onResume()

    if (CALCULATOR_RESULT != null) {
        amount_input.setText(CALCULATOR_RESULT)
    }
}

override fun onDestroy() {
    super.onDestroy()

    CALCULATOR_RESULT = null
}

override fun onNothingSelected(parent: AdapterView<*>?) {

}

override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
    var item: String = parent?.getItemAtPosition(position).toString()
    CATEGORY_SPINNER_VALUE = item
}

fun generateResourceString(resourceId: Int): String {
    var resourceString = getResources().getString(resourceId)

    return resourceString
}

fun saveRecord() {
    val recordId: Int = intent.getIntExtra(RECORD_ID, -1)
    val recordCategory = CATEGORY_SPINNER_VALUE
    val recordAmount = amount_input.text.toString().replace("-", "")
    val recordDate = RECORD_DATE_VALUE
    val recordDescription = description_input.text.toString()

    val formatRecordAmount = DecimalFormat("##.##")

    var formattedRecordAmount: String? = null

    if (recordCategory == "Choose a category" || recordCategory == "Elige una categoría") {
        Toast.makeText(this, R.string.choose_a_category_toast_message, Toast.LENGTH_SHORT).show()
        return
    } else if (recordAmount.trim().isEmpty()) {
        Toast.makeText(this, R.string.insert_amount_toast_message, Toast.LENGTH_SHORT).show()
        return
    } else if (recordDate == null) {
        Toast.makeText(this, R.string.select_a_date_toast_message, Toast.LENGTH_SHORT).show()
        return
    } else if (recordDescription.trim().isEmpty()) {
        Toast.makeText(this, R.string.insert_description_toast_message, Toast.LENGTH_SHORT).show()
        return
    } else if (!IS_IMAGE_SELECTED) {
        Toast.makeText(this, R.string.select_a_reason_toast_message, Toast.LENGTH_SHORT).show()
        return
    } else if (recordAmount.trim().isNotEmpty()) {
        formattedRecordAmount = formatRecordAmount.format(recordAmount.toDouble())
    }

    val intent = Intent()

    intent.putExtra(RECORD_CATEGORY, recordCategory)
    intent.putExtra(RECORD_AMOUNT, formattedRecordAmount)
    intent.putExtra(RECORD_DATE, recordDate)
    intent.putExtra(RECORD_DESCRIPTION, recordDescription)
    intent.putExtra(RECORD_IMAGE, RECORD_IMAGE_PICKED)
    intent.putExtra(RECORD_IMAGE_DESCRIPTION, RECORD_IMAGE_PICKED_DESCRIPTION)

    if (recordId != -1) {
        intent.putExtra(RECORD_ID, recordId)
    }

    CALCULATOR_RESULT = null

    IS_IMAGE_SELECTED = false

    setResult(Activity.RESULT_OK, intent)
    finish()
}

fun addRecordImages() {
    recordImages.add(RecordImageAndDescription("comida", generateResourceString(R.string.food)))
    recordImages.add(RecordImageAndDescription("comision", generateResourceString(R.string.comission)))
    recordImages.add(RecordImageAndDescription("donacion", generateResourceString(R.string.donation)))
    recordImages.add(RecordImageAndDescription("educacion", generateResourceString(R.string.education)))
    recordImages.add(RecordImageAndDescription("egreso_general", generateResourceString(R.string.general_expense)))
    recordImages.add(RecordImageAndDescription("entretenimiento", generateResourceString(R.string.entertainment)))
    recordImages.add(RecordImageAndDescription("envios", generateResourceString(R.string.shipping)))
    recordImages.add(RecordImageAndDescription("gasolina", generateResourceString(R.string.gas)))
    recordImages.add(RecordImageAndDescription("hardware", generateResourceString(R.string.hardware)))
    recordImages.add(RecordImageAndDescription("hospedaje", generateResourceString(R.string.lodging)))
    recordImages.add(RecordImageAndDescription("impuestos", generateResourceString(R.string.tax)))
    recordImages.add(RecordImageAndDescription("ingreso_general", generateResourceString(R.string.general_income)))
    recordImages.add(RecordImageAndDescription("mineria", generateResourceString(R.string.mining)))
    recordImages.add(RecordImageAndDescription("prestamo", generateResourceString(R.string.loan)))
    recordImages.add(RecordImageAndDescription("renta", generateResourceString(R.string.rent)))
    recordImages.add(
        RecordImageAndDescription(
            "reparacion_de_casa",
            generateResourceString(R.string.house_repairment)
        )
    )
    recordImages.add(
        RecordImageAndDescription(
            "reparacion_de_vehiculo",
            generateResourceString(R.string.car_repairment)
        )
    )
    recordImages.add(RecordImageAndDescription("reparaciones", generateResourceString(R.string.repairment)))
    recordImages.add(RecordImageAndDescription("salud", generateResourceString(R.string.health)))
    recordImages.add(RecordImageAndDescription("servicios", generateResourceString(R.string.services)))
    recordImages.add(RecordImageAndDescription("software", generateResourceString(R.string.software)))
    recordImages.add(RecordImageAndDescription("subscription", generateResourceString(R.string.subscription)))
    recordImages.add(RecordImageAndDescription("telefonia", generateResourceString(R.string.telephony)))
    recordImages.add(RecordImageAndDescription("tiempo_familiar", generateResourceString(R.string.family_time)))
    recordImages.add(RecordImageAndDescription("transporte", generateResourceString(R.string.transportation)))
    recordImages.add(RecordImageAndDescription("ventas", generateResourceString(R.string.sales)))
    recordImages.add(RecordImageAndDescription("viaje", generateResourceString(R.string.travel)))
    recordImages.add(RecordImageAndDescription("lighting", generateResourceString(R.string.basic_services)))
}
}

2 个答案:

答案 0 :(得分:1)

这可能是由于图像内存问题,请使用GlidePicasso这是Android上最好的两个图像缓存库。

示例实现

滑行

Glide
.with(myFragment)
.load(url)
.centerCrop()
.placeholder(R.drawable.loading_spinner)
.into(myImageView);

毕加索

Picasso.get().load(R.drawable.landing_screen).into(imageView1);

有关更多信息,请从给定的链接中阅读各自的文档。 干杯。

编辑

有关位于项目文件夹中的图像文件,请访问:

Picasso.get().load("file:///android_asset/asset.png").into(imageView2);
Picasso.get().load(new File(...)).into(imageView3);

答案 1 :(得分:0)

一般而言,有三种策略:

  • 完美的图像-在其他地方创建图像集合,以便在活动开始时不必加载它们。
  • 显示RecyclerView,然后将图像加载到非UI线程上,然后使用图像刷新RecyclerView
  • 每个单元格的延迟加载图像(类似于上面的内容,但是您将对每个单元格而不是整个视图进行延迟加载,因此稍微复杂一点)

最后,您的图片可能太大了,您可能会考虑优化其大小,并可能有两种版本-一种用于RecyclerView,另一种用于全屏显示。