以下內容為原創,轉載時請注明鏈接地址:http://www.cnblogs.com/tiantianbyconan/p/3311658.html
這是我現在碰到的一個問題,如果需要在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>
