TextView加载大文本发生卡顿

Posted lauryn_yin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TextView加载大文本发生卡顿相关的知识,希望对你有一定的参考价值。

大概100多kb的文本内容的时候,会发生这个问题,采用的就是原生的TextView,原因的话网上讲得也比较详细,有的甚至连加载流程也都讲出来了,总的来说就是描画文本的作业是在UI线程里进行的

解决方案的话,网上提了大概四个吧。

方法一,把TextView的宽度设定为一个数字或者match_parent。NG,至少对我来说不起任何作用

方法二,使用androidx.appcompat.widget.AppCompatTextView。同上

方法三,在方法二的基础上,采用下述方法,加载速度肉眼可见的有提升,关键是改动量比较小

import androidx.appcompat.widget.AppCompatTextView;	
import androidx.core.text.PrecomputedTextCompat;	
import java.util.concurrent.Future;
。。。。
//关键代码
Future<PrecomputedTextCompat> future = PrecomputedTextCompat.getTextFuture(contentDelayed, txtViewContent.getTextMetricsParamsCompat(), null);
txtViewContent.setTextFuture(future);

方法四,相对方法三来说,改动量有点大:使用StaticLayout,具体原因以及理由网上有,可以自行百度。其实这个方法相当于是一个自定义view了。

参考:https://www.jianshu.com/p/a9d6fbf20642

import android.content.Context;
import android.graphics.Canvas;
import android.text.Layout;
import android.util.AttributeSet;
import android.view.View;

public class StaticLayoutView extends View 

	private Layout mLayout = null;

	private int mWidth;
	private int mHeight;

	public StaticLayoutView(Context context) 
		super(context);
	

	public StaticLayoutView(Context context, AttributeSet attrs) 
		super(context, attrs);
	

	public StaticLayoutView(Context context, AttributeSet attrs,int defStyleAttr) 
		super(context, attrs, defStyleAttr);
	

	public void setLayout(Layout layout) 
		if (layout == null) 
			return;
		
		
		mLayout = layout;
		if (mLayout.getWidth() != mWidth || mLayout.getHeight() != mHeight) 
			mWidth = mLayout.getWidth();
			mHeight = mLayout.getHeight();
			requestLayout();
		
	

	@Override
	protected void onDraw(Canvas canvas) 
		super.onDraw(canvas);
		canvas.save();
		if (mLayout != null) 
			mLayout.draw(canvas, null, null, 0);
		
		canvas.restore();
	

	@Override
	protected void onLayout(boolean changed, int left, int top, int right, int bottom) 
		super.onLayout(changed, left, top, right, bottom);
	

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
		if (mLayout != null) 
			setMeasuredDimension(mLayout.getWidth(), mLayout.getHeight());
		 else 
			super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		
	

public class StaticLayoutManager 

    public StaticLayout longStringLayout;

    private TextPaint textPaint;
    private Layout.Alignment alignment;


    private int hardCodeWidth;

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    public void initLayout(Context context, CharSequence longString) 

        textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        textPaint.density = context.getResources().getDisplayMetrics().density;
        textPaint.setTextSize(DisplayUtils.fromDPtoPix(context, DisplayUtils.TEXT_SIZE_DP));
        
        alignment = Layout.Alignment.ALIGN_NORMAL;

        hardCodeWidth = DisplayUtils.getScreenWidth(context);

        longStringLayout = new StaticLayout(longString, textPaint, hardCodeWidth, alignment, 1.0f, 0f, true);
    


    public StaticLayout getLongStringLayout() 
        return longStringLayout;
    

    private static StaticLayoutManager INSTANCE = null;

    public static StaticLayoutManager getInstance() 
        if (INSTANCE == null) 
            INSTANCE = new StaticLayoutManager();
        
        return INSTANCE;
    

使用方法

public class StaticLayoutAty extends AppCompatActivity 

    private String readFile() 
        try 
            InputStream is = getAssets().open("0.txt");
            int size = is.available();
            byte[] buffer = new byte[size];
            is.read(buffer);
            is.close();
            return new String(buffer);
         catch (IOException e) 
            return "读取错误...";
        
    

    StaticLayoutView staticLayoutView;
    ProgressDialog pd;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_static_layout_aty);
        staticLayoutView = findViewById(R.id.static_content);
        pd = new ProgressDialog(this);
        pd.show();
        new Thread(new Runnable() 
            @Override
            public void run() 
                StaticLayoutManager.getInstance().initLayout(StaticLayoutAty.this,  readFile());

                runOnUiThread(new Runnable() 
                    @Override
                    public void run() 
                        staticLayoutView.setLayout(StaticLayoutManager.getInstance().getLongStringLayout());
                        Toast.makeText(StaticLayoutAty.this, "init span finish", Toast.LENGTH_LONG).show();
                        pd.dismiss();
                    
                );
            
        ).start();
    
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorAccent"
    tools:context=".activity.StaticLayoutAty">

    <com.xx.StaticLayoutView
        android:id="@+id/static_content"
        android:layout_width="fill_parent"
        android:layout_height="match_parent"/>

</ScrollView>

PS:方法四在试验的时候还是有问题,progressDialog消失了10多秒之后,文本才加载出来,而且还会ANR,可能是用的不对?

以上是关于TextView加载大文本发生卡顿的主要内容,如果未能解决你的问题,请参考以下文章

TextView加载大文本发生卡顿

TextView加载大文本发生卡顿

AppCompatTextView自动缩放字体在RecyclerView中卡顿,自定义高效自动缩放TextView

在从 NSMutableDictionary 加载的 textview 中保存更改的文本

Android TextView加载html形式文本

如何根据加载的文本增加我的android textview中的文本大小?