这是我现在碰到的一个问题,如果需要在TextView中加载大文本的时候,比如几M的txt文件时,TextView载入的时候会出现卡死的现象,甚至会出现异常等待退出出现。
解决办法之一就是通过“分段”或“分页”来显示数据,在TextView(嵌入在ScrollView之中实现了TextView的滚动)中滚动到底部的时候,再去加载下一部分的数据,依次类推,这样每次加载的数据相对来说都比较小,不会出现卡顿的现象。
遇到的问题是,如何监听ScrollView滚动的位置(滚动到顶部还是底部?)。
如下,通过自定义ScrollView类(BorderScrollView):
1 packagecom.wangjie.bigtextloadtest;2
3 importandroid.content.Context;4 importandroid.graphics.Rect;5 importandroid.util.AttributeSet;6 importandroid.widget.ScrollView;7
8 /**
9 * Created with IntelliJ IDEA.10 * Author: wangjie email:tiantian.china.2@gmail.com11 * Date: 13-9-612 * Time: 下午2:0613 */
14 public class BorderScrollView extendsScrollView{15 private longmillis;16 //滚动监听者
17 privateOnScrollChangedListener onScrollChangedListener;18
19 publicBorderScrollView(Context context) {20 super(context);21 }22
23 publicBorderScrollView(Context context, AttributeSet attrs) {24 super(context, attrs);25 }26
27 public BorderScrollView(Context context, AttributeSet attrs, intdefStyle) {28 super(context, attrs, defStyle);29 }30
31 @Override32 protected void onScrollChanged(int l, int t, int oldl, intoldt) {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 publicOnScrollChangedListener getOnScrollChangedListener() {64 returnonScrollChangedListener;65 }66
67 public voidsetOnScrollChangedListener(OnScrollChangedListener onScrollChangedListener) {68 this.onScrollChangedListener =onScrollChangedListener;69 }70
71 /**
72 * 获得滚动总长度73 *@return
74 */
75 public intgetTotalVerticalScrollRange() {76 return this.computeVerticalScrollRange();77 }78
79 @Override80 protected intcomputeScrollDeltaToGetChildRectOnScreen(Rect rect) {81 return 0; //禁止ScrollView在子控件的布局改变时自动滚动
82 }83
84 }
滚动监听器接口OnScrollChangedListener:
1 packagecom.wangjie.bigtextloadtest;2
3 /**
4 * Created with IntelliJ IDEA.5 * Author: wangjie email:tiantian.china.2@gmail.com6 * Date: 13-9-67 * Time: 下午2:538 */
9 public interfaceOnScrollChangedListener {10 /**
11 * 监听滚动变化12 *@paraml13 *@paramt14 *@paramoldl15 *@paramoldt16 */
17 public void onScrollChanged(int l, int t, int oldl, intoldt);18
19 /**
20 * 监听滚动到顶部21 */
22 public voidonScrollTop();23
24 /**
25 * 监听滚动到底部26 */
27 public voidonScrollBottom();28
29 }
滚动监听器的空实现OnScrollChangedListenerSimple(简洁真正用时候的代码):
1 packagecom.wangjie.bigtextloadtest;2
3 /**
4 * Created with IntelliJ IDEA.5 * Author: wangjie email:tiantian.china.2@gmail.com6 * Date: 13-9-97 * Time: 下午2:398 */
9 public class OnScrollChangedListenerSimple implementsOnScrollChangedListener{10 @Override11 public void onScrollChanged(int l, int t, int oldl, intoldt) {}12
13 @Override14 public voidonScrollTop() {}15
16 @Override17 public voidonScrollBottom() {}18 }
异步加载分段文本(这里每次加载50行):
1 packagecom.wangjie.bigtextloadtest;2
3 importandroid.content.Context;4 importandroid.os.AsyncTask;5 importandroid.os.Handler;6 importandroid.view.View;7
8 import java.io.*;9
10 /**
11 * Created with IntelliJ IDEA.12 * Author: wangjie email:tiantian.china.2@gmail.com13 * Date: 13-9-614 * Time: 上午11:3415 */
16 public class AsyncTextLoadTask extends AsyncTask{17 privateContext context;18 privateMainActivity activity;19 privateBufferedReader br;20
21 publicAsyncTextLoadTask(Context context, BufferedReader br) {22 this.context =context;23 this.br =br;24 activity =(MainActivity)context;25 }26
27 @Override28 protectedString doInBackground(Object... params) {29 StringBuilder paragraph = newStringBuilder();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 returnparagraph.toString();45 }46
47
48 @Override49 protected voidonPreExecute() {50 super.onPreExecute();51 }52
53 @Override54 protected voidonPostExecute(String result) {55 super.onPostExecute(result);56 activity.contentTv.setText(result);57 new Handler().postDelayed(newRunnable() {58
59 @Override60 public voidrun() {61 activity.contentScroll.scrollTo(0, 0); //记载完新数据后滚动到顶部
62 }63 }, 100);64 activity.isLoading = false;65 }66
67 }
真正使用分段加载数据Activity(这里加载一本小说《百年孤独》):
1 packagecom.wangjie.bigtextloadtest;2
3 importandroid.app.Activity;4 importandroid.content.Context;5 importandroid.os.Bundle;6 importandroid.widget.TextView;7
8 importjava.io.BufferedReader;9 importjava.io.IOException;10 importjava.io.InputStream;11 importjava.io.InputStreamReader;12
13 public class MainActivity extendsActivity {14 publicBorderScrollView contentScroll;15 publicTextView contentTv;16
17 privateBufferedReader br;18
19 privateContext context;20
21 public booleanisLoading;22
23
24 /**
25 * Called when the activity is first created.26 */
27 @Override28 public voidonCreate(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(newOnScrollChangedListenerSimple(){38 @Override39 public voidonScrollBottom() {40 synchronized (MainActivity.class){41 if(!isLoading){42 isLoading = true;43 newAsyncTextLoadTask(context, br).execute();44 }45 }46 }47 });48
49 try{50 InputStream is = context.getAssets().open("bngd.txt");51 br = new BufferedReader(newInputStreamReader(is));52
53 newAsyncTextLoadTask(context, br).execute();54
55 }catch(Exception ex){56 ex.printStackTrace();57 }58
59
60 }61
62
63 @Override64 protected voidonDestroy() {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
3 android:orientation="vertical"
4 android:layout_width="fill_parent"
5 android:layout_height="fill_parent"
6 >
7
9 android:layout_width="fill_parent"
10 android:layout_height="fill_parent"
11 >
12
14 android:layout_width="fill_parent"
15 android:layout_height="fill_parent"
16 >
17
19 android:layout_height="wrap_content"
20 android:text="asdfasdf"
21 />
22
24 android:layout_width="fill_parent"
25 android:layout_height="wrap_content"
26 android:text="Hello World, MainActivity"
27 />
28
29
30
31
32
33