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加载大文本发生卡顿的主要内容,如果未能解决你的问题,请参考以下文章