【Android】RecyclerView卡顿问题jerky

本文探讨了如何解决RecyclerView在滚动时出现卡顿的问题,重点在于发现并处理onBindView中的IO操作,尤其是Glide加载多图片时保存Bitmap到文件导致的延迟。通过将IO操作放到后台线程,利用ThreadPoolExecutor或ExecutorService,成功实现了流畅的滚动体验并确保了Bitmap的本地保存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

解决RecyclerView卡顿的问题,找过很多问题的引发点,最后的解决灵感来自于这里:
onBindView里的IO操作导致RecyclerView scroll 卡顿
在项目中查找,发现onBindView中多图片使用Glide加载时确实是有保存bitmap到文件的IO操作,将IO操作注释掉,运行App,卡顿消失,这样,开始对IO动刀;
首先想到,每个IO操作新开线程来处理,为加快线程速度,保证预期效果不打太大折扣,想到利用ThreadPoolExecutor或者是ExecutorService进行
代码:

/*
   * 保存 bitmap到文件,并将文件路径返回,利用线程池新开IO线程,解决滚动时卡顿的问题
   * */
    public static String getFilePath(final Bitmap bitmap, String fileName) {

        final File picDir = Environment.getExternalStoragePublicDirectory(AppConfig.DIR_ROOT_PIC);
        final File f = new File(picDir, fileName + AppConfig.FILE_NAME_EXTENSION_PIC);
        try {
            final FileOutputStream fOut = new FileOutputStream(f);
            App.getThreadPool().execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        f.createNewFile();
                        bitmap.compress(Bitmap.CompressFormat.PNG, 30, fOut);
                        try {
                            fOut.flush();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        try {
                            fOut.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return f.getAbsolutePath();
    }

这样,就在保证recyclerView平滑滚动的同时,保存了Bitmap到本地。

#include "ti_msp_dl_config.h" #include "motor.h" #include "PID.h" #include "xunji.h" #include "atk_ms901m.h" //#include "oled_software_i2c.h" #define LED_ON DL_GPIO_clearPins(GPIO_LED_PORT,GPIO_LED_PIN_0_PIN) //用于各种检验的灯 #define MIN_DUTY 15 // 电机最小启动duty(需实测) //初始pwm int16_t baseSpeed = 35; //int16_t SpeedL = 0, SpeedR = 0; //uint8_t key1_flag; //encoder volatile int32_t enco_l; volatile int32_t enco_r; volatile uint32_t gpioA,gpioB; volatile int32_t enco_l_last,enco_r_last; //speed float speed_l,speed_r; float target_speed_l = 100.0f; // 左轮目标速度(mm/s) float target_speed_r = 100.0f; // 右轮目标速度(mm/s) //uart uint32_t gEchoData; uint32_t date[20]; uint8_t date_index; //检验 uint32_t A; //imu601结构体初始化 atk_ms901m_attitude_data_t attitude_dat; // pid结构体初始化 PID pid_left; // 左轮PID控制器 PID pid_right; // 右轮PID控制器 // 初始化PID(示例参数,需调试) void PID_Init_Config(void) { PID_Init(&pid_left, 1.0f, 0.5f, 0.1f, 100.0f); // P=2, I=0.5, D=0.1,输出限幅±100 PID_Init(&pid_right, 1.0f, 0.5f, 0.1f, 100.0f); // 左右轮参数可相同或独立调整 } //K230通信处理函数 void K230_REC(void) { if(gEchoData==0) { DL_GPIO_setPins(GPIO_LED_PORT,GPIO_LED_PIN_0_PIN); } else { DL_GPIO_clearPins(GPIO_LED_PORT, GPIO_LED_PIN_0_PIN); } } //主函数 int main(void) { SYSCFG_DL_init(); //uart初始化 NVIC_ClearPendingIRQ(UART_0_INST_INT_IRQN); NVIC_EnableIRQ(UART_0_INST_INT_IRQN); //编码器初始化 NVIC_EnableIRQ(ENCODER_GPIOA_INT_IRQN); NVIC_EnableIRQ(ENCODER_GPIOB_INT_IRQN); //定时器初始化 NVIC_ClearPendingIRQ(TIMER_0_INST_INT_IRQN); NVIC_EnableIRQ(TIMER_0_INST_INT_IRQN); //pid初始化 PID_Init_Config(); //初始化给占空比 Set_Speed(0, baseSpeed); Set_Speed(1, baseSpeed); //电机初始化 Motor_On(); //陀螺仪初始化 atk_ms901m_uart_init();//初始化函数 atk_ms901m_get_attitude(&attitude_dat, 100);//获取参数,第一个参数是结构体,第二个参数是out time(s失联时间) //oled初始化 //OLED_Init(); while (1) { K230_REC(); } } //编码器计数更新 void encoder_update(void) { // 关闭全局中断(或仅关闭编码器中断) __disable_irq(); enco_l_last = enco_l; enco_r_last = enco_r; enco_l = 0; enco_r = 0; // 恢复全局中断 __enable_irq(); // 计算速度(单位:mm/s,假设车轮周长=π*直径=3.14*65mm=204.1mm) // 公式:速度 = (脉冲数 / 每圈脉冲数) * 周长 / 时间周期 // 每圈脉冲数 = 编码器线数 × 减速比 = 13 × 28 = 364脉冲/圈 // 时间周期=20ms(假设定时器中断周期为20ms,即0.02秒) float per_round_pulse = 13.0f * 28.0f; // 364脉冲/圈 float wheel_circumference = 3.14159f * 65.0f; // 车轮周长(mm) float time_period = 0.02f; // 20ms = 0.02秒 speed_l = (enco_l_last / per_round_pulse) * wheel_circumference / time_period; // 左轮速度(mm/s) speed_r = (enco_r_last / per_round_pulse) * wheel_circumference / time_period; // 右轮速度(mm/s) } //速度pid控制 void speed_control(void) { //zuolun pid float duty_l = PID_Realize(&pid_left, speed_l, target_speed_l); //youlun pid float duty_r = PID_Realize(&pid_right, speed_r, target_speed_r); // 死区补偿:若duty绝对值小于MIN_DUTY,强制设为MIN_DUTY(方向不变) if (duty_l > 0 && duty_l < MIN_DUTY) duty_l = MIN_DUTY; if (duty_l < 0 && duty_l > -MIN_DUTY) duty_l = -MIN_DUTY; if (duty_r > 0 && duty_r < MIN_DUTY) duty_r = MIN_DUTY; if (duty_r < 0 && duty_r > -MIN_DUTY) duty_r = -MIN_DUTY; //通过Set_Speed输出PWM占空比(duty已由PID限幅为-100~100) Set_Speed(0, (int8_t)duty_l); // 0=左轮,传递计算的duty值 Set_Speed(1, (int8_t)duty_r); // 1=右轮 } //陀螺仪控制左右转 //void turn(float ) void GROUP1_IRQHandler(void) { //获取中断信号 gpioA = DL_GPIO_getEnabledInterruptStatus(GPIOA,ENCODER_E2A_PIN); gpioB = DL_GPIO_getEnabledInterruptStatus(GPIOB,ENCODER_E1A_PIN); //ENCODER RIGHT if((gpioA&ENCODER_E2A_PIN)!=0) { if(!DL_GPIO_readPins(ENCODER_E2B_PORT,ENCODER_E2B_PIN)) { enco_r++; } else { enco_r--; } DL_GPIO_clearInterruptStatus(GPIOA, ENCODER_E2A_PIN); } //ENCODER LEFT if((gpioB&ENCODER_E1A_PIN)!=0) { if(!DL_GPIO_readPins(ENCODER_E1B_PORT,ENCODER_E1B_PIN)) { enco_l--; } else { enco_l++; } DL_GPIO_clearInterruptStatus(GPIOB,ENCODER_E1A_PIN); } } void TIMER_0_INST_IRQHandler(void) { switch (DL_TimerA_getPendingInterrupt(TIMER_0_INST)) { case DL_TIMERA_IIDX_ZERO: // 处理计数到零的中断 encoder_update(); //xunji(); speed_control(); A++; break; default: break; } } void UART_0_INST_IRQHandler(void) { switch (DL_UART_Main_getPendingInterrupt(UART_0_INST)) { /*! UART interrupt index for UART receive */ case DL_UART_MAIN_IIDX_RX: gEchoData = DL_UART_Main_receiveData(UART_0_INST); //DL_GPIO_clearPins(GPIO_LED_PORT,GPIO_LED_PIN_0_PIN); //DL_UART_Main_transmitData(UART_0_INST, gEchoData); DL_UART_Main_transmitData(UART_0_INST,gEchoData); break; default: break; } } 为什么我的速度环那么搞笑,车轮一卡一卡
最新发布
07-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值