Android自定义ScrollView分段加载大文本数据到TextView


这是我现在碰到的一个问题,如果需要在TextView中加载大文本的时候,比如几M的txt文件时,TextView载入的时候会出现卡死的现象,甚至会出现异常等待退出出现。

解决办法之一就是通过“分段”或“分页”来显示数据,在TextView(嵌入在ScrollView之中实现了TextView的滚动)中滚动到底部的时候,再去加载下一部分的数据,依次类推,这样每次加载的数据相对来说都比较小,不会出现卡顿的现象。

遇到的问题是,如何监听ScrollView滚动的位置(滚动到顶部还是底部?)。

 

如下,通过自定义ScrollView类(BorderScrollView):


 1 package com.wangjie.bigtextloadtest;
2
3 import android.content.Context;
4 import android.graphics.Rect;
5 import android.util.AttributeSet;
6 import android.widget.ScrollView;
7
8 /
9 Created with IntelliJ IDEA.
10 Author: wangjie email:tiantian.china.2@gmail.com
11 Date: 13-9-6
12 Time: 下午2:06
13 */
14 public class BorderScrollView extends ScrollView{
15 private long millis;
16 // 滚动监听者
17 private OnScrollChangedListener onScrollChangedListener;
18
19 public BorderScrollView(Context context) {
20 super(context);
21 }
22
23 public BorderScrollView(Context context, AttributeSet attrs) {
24 super(context, attrs);
25 }
26
27 public BorderScrollView(Context context, AttributeSet attrs, int defStyle) {
28 super(context, attrs, defStyle);
29 }
30
31 @Override
32 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
33 super.onScrollChanged(l, t, oldl, oldt);
34
35 if(null == onScrollChangedListener){
36 return;
37 }
38
39 long now = System.currentTimeMillis();
40
41 // 通知监听者当前滚动的具体信息
42 onScrollChangedListener.onScrollChanged(l, t, oldl, oldt);
43
44 if(now - millis > 1000l){
45 // 滚动到底部(前提:从不是底部滚动到底部)
46 if((this.getHeight() + oldt) != this.getTotalVerticalScrollRange()
47 && (this.getHeight() + t) == this.getTotalVerticalScrollRange()){
48
49 onScrollChangedListener.onScrollBottom(); // 通知监听者滚动到底部
50
51 millis = now;
52 }
53 }
54
55 // 滚动到顶部(前提:从不是顶部滚动到顶部)
56 if(oldt != 0 && t == 0){
57 onScrollChangedListener.onScrollTop(); // 通知监听者滚动到顶部
58 }
59
60
61 }
62
63 public OnScrollChangedListener getOnScrollChangedListener() {
64 return onScrollChangedListener;
65 }
66
67 public void setOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) {
68 this.onScrollChangedListener = onScrollChangedListener;
69 }
70
71 /
72 获得滚动总长度
73 @return
74 */
75 public int getTotalVerticalScrollRange() {
76 return this.computeVerticalScrollRange();
77 }
78
79 @Override
80 protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
81 return 0; // 禁止ScrollView在子控件的布局改变时自动滚动
82 }
83
84 }

 

滚动监听器接口OnScrollChangedListener:


 1 package com.wangjie.bigtextloadtest;
2
3 /
4 Created with IntelliJ IDEA.
5 Author: wangjie email:tiantian.china.2@gmail.com
6 Date: 13-9-6
7 Time: 下午2:53
8 */
9 public interface OnScrollChangedListener {
10 /
11 监听滚动变化
12 @param l
13 @param t
14 @param oldl
15 @param oldt
16 /
17 public void onScrollChanged(int l, int t, int oldl, int oldt);
18
19 /
20 监听滚动到顶部
21 /
22 public void onScrollTop();
23
24 /
25 监听滚动到底部
26 /
27 public void onScrollBottom();
28
29 }

 

滚动监听器的空实现OnScrollChangedListenerSimple(简洁真正用时候的代码):


 1 package com.wangjie.bigtextloadtest;
2
3 /*
4 Created with IntelliJ IDEA.
5 Author: wangjie email:tiantian.china.2@gmail.com
6 Date: 13-9-9
7 Time: 下午2:39
8 /
9 public class OnScrollChangedListenerSimple implements OnScrollChangedListener{
10 @Override
11 public void onScrollChanged(int l, int t, int oldl, int oldt) {}
12
13 @Override
14 public void onScrollTop() {}
15
16 @Override
17 public void onScrollBottom() {}
18 }

 

异步加载分段文本(这里每次加载50行):


 1 package com.wangjie.bigtextloadtest;
2
3 import android.content.Context;
4 import android.os.AsyncTask;
5 import android.os.Handler;
6 import android.view.View;
7
8 import java.io.;
9
10 /**
11
Created with IntelliJ IDEA.
12 Author: wangjie email:tiantian.china.2@gmail.com
13 Date: 13-9-6
14 Time: 上午11:34
15 /
16 public class AsyncTextLoadTask extends AsyncTask<Object, String, String> {
17 private Context context;
18 private MainActivity activity;
19 private BufferedReader br;
20
21 public AsyncTextLoadTask(Context context, BufferedReader br) {
22 this.context = context;
23 this.br = br;
24 activity = (MainActivity)context;
25 }
26
27 @Override
28 protected String doInBackground(Object… params) {
29 StringBuilder paragraph = new StringBuilder();
30 try {
31
32 String line = “”;
33
34 int index = 0;
35 while(index < 50 && (line = br.readLine()) != null){
36 paragraph.append(line + “\n”);
37 index++;
38 }
39
40 } catch (IOException e) {
41 e.printStackTrace();
42 }
43
44 return paragraph.toString();
45 }
46
47
48 @Override
49 protected void onPreExecute() {
50 super.onPreExecute();
51 }
52
53 @Override
54 protected void onPostExecute(String result) {
55 super.onPostExecute(result);
56 activity.contentTv.setText(result);
57 new Handler().postDelayed(new Runnable() {
58
59 @Override
60 public void run() {
61 activity.contentScroll.scrollTo(0, 0); // 记载完新数据后滚动到顶部
62 }
63 }, 100);
64 activity.isLoading = false;
65 }
66
67 }

 

真正使用分段加载数据Activity(这里加载一本小说《百年孤独》):


 1 package com.wangjie.bigtextloadtest;
2
3 import android.app.Activity;
4 import android.content.Context;
5 import android.os.Bundle;
6 import android.widget.TextView;
7
8 import java.io.BufferedReader;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.io.InputStreamReader;
12
13 public class MainActivity extends Activity {
14 public BorderScrollView contentScroll;
15 public TextView contentTv;
16
17 private BufferedReader br;
18
19 private Context context;
20
21 public boolean isLoading;
22
23
24 /*
25 Called when the activity is first created.
26 */
27 @Override
28 public void onCreate(Bundle savedInstanceState) {
29 super.onCreate(savedInstanceState);
30 setContentView(R.layout.main);
31 context = this;
32
33 contentTv = (TextView) findViewById(R.id.content);
34 contentScroll = (BorderScrollView) findViewById(R.id.contentScroll);
35
36 // 注册刚写的滚动监听器
37 contentScroll.setOnScrollChangedListener(new OnScrollChangedListenerSimple(){
38 @Override
39 public void onScrollBottom() {
40 synchronized (MainActivity.class){
41 if(!isLoading){
42 isLoading = true;
43 new AsyncTextLoadTask(context, br).execute();
44 }
45 }
46 }
47 });
48
49 try{
50 InputStream is = context.getAssets().open(“bngd.txt”);
51 br = new BufferedReader(new InputStreamReader(is));
52
53 new AsyncTextLoadTask(context, br).execute();
54
55 }catch(Exception ex){
56 ex.printStackTrace();
57 }
58
59
60 }
61
62
63 @Override
64 protected void onDestroy() {
65 super.onDestroy();
66 if(null != br){
67 try {
68 br.close();
69 } catch (IOException e) {
70 e.printStackTrace();
71 }
72 }
73 }
74
75 }

 

贴上布局:


 1 <?xml version=”1.0” encoding=”utf-8”?>
2 <LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android
3 android:orientation=”vertical”
4 android:layout_width=”fill_parent”
5 android:layout_height=”fill_parent”
6 >
7 <com.wangjie.bigtextloadtest.BorderScrollView
8 android:id=”@+id/contentScroll”
9 android:layout_width=”fill_parent”
10 android:layout_height=”fill_parent”
11 >
12 <LinearLayout
13 android:orientation=”vertical”
14 android:layout_width=”fill_parent”
15 android:layout_height=”fill_parent”
16 >
17 <TextView
18 android:layout_width=”fill_parent”
19 android:layout_height=”wrap_content”
20 android:text=”asdfasdf”
21 />
22 <TextView
23 android:id=”@+id/content”
24 android:layout_width=”fill_parent”
25 android:layout_height=”wrap_content”
26 android:text=”Hello World, MainActivity”
27 />
28 </LinearLayout>
29
30 </com.wangjie.bigtextloadtest.BorderScrollView>
31
32
33 </LinearLayout>

 

 



来源博客:Wang Jie's Blog
本文链接:https://blog.wangjiegulu.com/2013/09/10/Android自定义ScrollView分段加载大文本数据到TextView/
版权声明:本博客所有文章除特别声明外,均采用 CC BY 4.0 CN协议 许可协议。转载请注明出处。