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

简介:

以下内容为原创,转载时请注明链接地址: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>
复制代码

 

 

本文转自天天_byconan博客园博客,原文链接:http://www.cnblogs.com/tiantianbyconan/p/3311658.html ,如需转载请自行联系原作者
相关文章
|
Android开发 UED 计算机视觉
Android自定义view之线条等待动画(灵感来源:金铲铲之战)
本文介绍了一款受游戏“金铲铲之战”启发的Android自定义View——线条等待动画的实现过程。通过将布局分为10份,利用`onSizeChanged`测量最小长度,并借助画笔绘制动态线条,实现渐变伸缩效果。动画逻辑通过四个变量控制线条的增长与回退,最终形成流畅的等待动画。代码中详细展示了画笔初始化、线条绘制及动画更新的核心步骤,并提供完整源码供参考。此动画适用于加载场景,提升用户体验。
778 5
Android自定义view之线条等待动画(灵感来源:金铲铲之战)
|
Android开发
Android自定义view之利用PathEffect实现动态效果
本文介绍如何在Android自定义View中利用`PathEffect`实现动态效果。通过改变偏移量,结合`PathEffect`的子类(如`CornerPathEffect`、`DashPathEffect`、`PathDashPathEffect`等)实现路径绘制的动态变化。文章详细解析了各子类的功能与参数,并通过案例代码展示了如何使用`ComposePathEffect`组合效果,以及通过修改偏移量实现动画。最终效果为一个菱形图案沿路径运动,源码附于文末供参考。
279 0
|
XML Java Android开发
Android自定义view之网易云推荐歌单界面
本文详细介绍了如何通过自定义View实现网易云音乐推荐歌单界面的效果。首先,作者自定义了一个圆角图片控件`MellowImageView`,用于绘制圆角矩形图片。接着,通过将布局放入`HorizontalScrollView`中,实现了左右滑动功能,并使用`ViewFlipper`添加图片切换动画效果。文章提供了完整的代码示例,包括XML布局、动画文件和Java代码,最终展示了实现效果。此教程适合想了解自定义View和动画效果的开发者。
557 65
Android自定义view之网易云推荐歌单界面
|
XML 前端开发 Android开发
一篇文章带你走近Android自定义view
这是一篇关于Android自定义View的全面教程,涵盖从基础到进阶的知识点。文章首先讲解了自定义View的必要性及简单实现(如通过三个构造函数解决焦点问题),接着深入探讨Canvas绘图、自定义属性设置、动画实现等内容。还提供了具体案例,如跑马灯、折线图、太极图等。此外,文章详细解析了View绘制流程(measure、layout、draw)和事件分发机制。最后延伸至SurfaceView、GLSurfaceView、SVG动画等高级主题,并附带GitHub案例供实践。适合希望深入理解Android自定义View的开发者学习参考。
1003 84
|
安全 数据库 Android开发
在Android开发中实现两个Intent跳转及数据交换的方法
总结上述内容,在Android开发中,Intent不仅是活动跳转的桥梁,也是两个活动之间进行数据交换的媒介。运用Intent传递数据时需注意数据类型、传输大小限制以及安全性问题的处理,以确保应用的健壯性和安全性。
723 11
|
前端开发 Android开发 UED
讲讲Android为自定义view提供的SurfaceView
本文详细介绍了Android中自定义View时使用SurfaceView的必要性和实现方式。首先分析了在复杂绘制逻辑和高频界面更新场景下,传统View可能引发卡顿的问题,进而引出SurfaceView作为解决方案。文章通过Android官方Demo展示了SurfaceView的基本用法,包括实现`SurfaceHolder.Callback2`接口、与Activity生命周期绑定、子线程中使用`lockCanvas()`和`unlockCanvasAndPost()`方法完成绘图操作。
372 3
|
Android开发 开发者
Android自定义view之围棋动画(化繁为简)
本文介绍了Android自定义View的动画实现,通过两个案例拓展动态效果。第一个案例基于`drawArc`方法实现单次动画,借助布尔值控制动画流程。第二个案例以围棋动画为例,从简单的小球直线运动到双向变速运动,最终实现循环动画效果。代码结构清晰,逻辑简明,展示了如何化繁为简实现复杂动画,帮助读者拓展动态效果设计思路。文末提供完整源码,适合初学者和进阶开发者学习参考。
256 0
Android自定义view之围棋动画(化繁为简)
|
Java Android开发 开发者
Android自定义view之围棋动画
本文详细介绍了在Android中自定义View实现围棋动画的过程。从测量宽高、绘制棋盘背景,到创建固定棋子及动态棋子,最后通过属性动画实现棋子的移动效果。文章还讲解了如何通过自定义属性调整棋子和棋盘的颜色及动画时长,并优化视觉效果,如添加渐变色让白子更明显。最终效果既可作为围棋动画展示,也可用作加载等待动画。代码完整,适合进阶开发者学习参考。
333 0
|
缓存 Java Android开发
|
10月前
|
移动开发 前端开发 Android开发
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
1777 12
【02】建立各项目录和页面标准化产品-vue+vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡

热门文章

最新文章