美文网首页
基于Android平台智能手机报系统的设计与开发

基于Android平台智能手机报系统的设计与开发

作者: 门心叼龙 | 来源:发表于2019-04-16 19:28 被阅读0次

    前言:

    本文写于2012年11月,转眼间7年的时间过去了,最近翻箱倒柜找出来了,看看7年之前写的代码和文章,简直不敢直视,哈哈哈,也没有修改直接分享出来,以示纪念。本文出自门心叼龙的博客,转载请注明出处。属于原创类容,侵权必究。 https://blog.csdn.net/geduo_83/article/details/85858394

    **1 ******研究意义****

    中国互联网发展迅速,据中国互联网络信息中心(CNNIC)发布的统计报告显示,截至2011年底,中国网民规模突破5亿,达到5.13亿,全年新增网民5580万,中国手机网民规模达到3.56亿,同比增长17.5%。随着智能手机的普及,庞大的智能手机网民规模为移动互联网应用的爆发提供了基础,各大互联网服务商也开始纷纷布局移动互联网,而激烈的竞争必将催生能够满足细分人群需求的创新应用,并进一步推动手机网民进入下一轮高速增长周期。

    移动互联网现在已经成为人们生活不可或缺的一部分,手机阅读报纸是依托手机媒介,由报纸和网络运营商联手搭建的信息传播平台,用户可通过手机浏览到当天发生的新闻,手机阅读方便,快捷,随时随地,为传统的互联网应用提供了新的发展空间和可持续发展的新商业模式,促进了移动网络宽带化的深入发展。通过本系统可以在智能手机上“原汁原味”直接阅读报纸版面和新闻,便捷和“原汁原味”,这正是智能手机报系统最有价值的地方。

    **2 ******NativeApp和WebApp优缺点分析****

    在智能手机上所运行的应用程序,根据开发方式的不同分为两种,一种是Native App,另外一种是Web App

    Web App无需安装,对设备碎片化的适应能力优于App,它只需要通过XHTML、CSS和JavaScript就可以在任意移动浏览器中执行。开发成本低、适配多种移动设备成本低、跨平台和终端、迭代更新容易、无需安装成本,但是不支持离线模式、消息推送不够及时、调用本地文件系统的能力弱。

    Native App因为位于平台层上方,向下访问和兼容的能力会比较好一些,提供最佳的用户体验,最优质的用户界面,最华丽的交互、针对不同平台提供不同体验、可节省带宽成本、可访问本地资源,但是移植到不同平台上比较麻烦、维持多个版本的成本比较高,App的开发成本要高很多,维持多个版本的更新升级比较麻烦

    智能手机报的核心功能是报纸阅读,需要上下翻页,为了提供最佳的用户体验,和优质的用户界面,本系统采用Native App方式开发

    **3 ******Android的架构分析****

    Android是一个移动设备的软件平台,是由Linux+Java构成的开源软件,它提供包括SDK、Apps、Middleware、Linux Kernel四个部分在内的全套手机软件方案。它开放了基于Linux内核以上的开发工具,从而保证了内容的可移植性和多样性。Android平台为我们开发应用程序提供了一套很好的框架,我们可以在这个平台的基础上开发不同的应用程序,也可以开发新的组件供应用程序调用。

    **3.1 ******Android架构****

    Android的架构是Linux内核、C/C++函数库、Dalvik虚拟机、应用框架以及关键应用程序构成的,如图2-1。通过编译基于框架的应用程序可以降低开发负荷。应用软件原则上是在Dalvik VM上运行的。

    第一层:Linux 内核,Display Rriver、Camera Driver、Flash Memory Driver、Wifi Driver它是整个Android系统最基础,最核心的部分

    第二层:系统运行库(程序库和运行库),主要包括SQLite(一个小型的关系型数据库),WebKit(一个开源的浏览器),OpenGL(3G开发API),同时在这一层还有个Android Runtime(android运行环境),主要包括Core Libraries(Java开发中常用的一些资源包)和Android运行虚拟机

    第三层:应用程序框架层(Application FrameWork),如:ActivtiyManager,ContentProvider,Window Manager(就是我们在开发Android应用程序,所需要的的一些框架)

    第四层:应用程序层(Application),如:Home,Contacts、phone等等

    **3.2 ******Android应用的构成和工作机制****

    对于一个Android应用程序来说,是由Activity、 BroadcastReceiver 、Service、ContentProvider四部分组成,但并不是每一个Android应用程序都必须由这四部分组成。在应用程序中使用时,需要在配置文件AndroidMainfest.xml中进行配置。这个配置文件是每个Android应用程序所必需的,用于定义应用程序的组件、组件的功能以及必要条件等。

    **3.2.1 ******Activity****

    Activity是构成应用程序中最重要的构造块, 在Android应用程序中,几乎都是通过Activity来与用户进行交互,所以Activity主要负责的就是创建与用户进行交互的显示窗口,你可以在这些窗口里通过调用setContentView(View)方法来显示你自己的用户界面。

    活动生命周期

    活动(Activity)在系统中以活动栈的形式进行管理。当一个新的活动启动后,被放到了栈项,成为了运行活动,而新活动之前的活动在活动栈里总位于新活动之下,直到新的活动退出才重新回到前台。

    (1)活动的整个生命期:从首次调用onCreate(Bundle)开始,到最终调用onDestroyO结束。在onCreate()中进行所有初始化,在onDestroyO时进行清理工作,释放资源。

    (2)活动的可见生命期:从调用onStart()开始,到onStop()被调用为止。在这段时间内,即使活动不与用户进行交互,用户也可以在屏幕上看到它。在这两个方法调用之间,可以维护活动显示给用户的资源。onStart()和onStop()方法可以多次调用,因为活动随时可以在可见和隐藏之间进行转换。

    (3)活动的后台生命期:从调用onResume()开始,到onPause()被调用为止。在这段时间内活动处于其它所有活动之前,并与用户进行交互。一个活动可以不断在resumed状态和paused状态之间变换[4]。

    活动之间的切换

    Android使用了Intent类来实现活动之间的切换工作。Intent负责对应用中一次操作的动作、动作涉及的数据和附加数据进行描述。根据Intent的描述,负责找到对应的组件,将Intent传递给调用的组件并完成组件的调用。因此,Intent起着一种媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦。在应用中,我们可以以两种形式来使用Intent:直接Intent,指定了component属性的Intent,通过指定具体的组件类,通知应用启动对应的组件。间接Intent,没有指定comonent属性的Intent,则需要包含足够的信息,这样系统才能根据这些信息,在所有的可用组件中,确定满足此Intent的组件。

    **3.2.2 ******BroadcastReceiver****

    BroadcastReceiver是用于对外部事件的响应,当外部事件发生时,会使用NotificationManager通知用户。当一个BroadcastReceiver被触发时,系统会在需要的时候启动对应的应用程序。如在本系统中,当用户正在其它界面进行操作时,有好友发送消息过来,就会以通知的形式发送到当前界面的正上方来通知用户。各种应用还可以通过使用Context.broadcastIntent()将它们的BroadcastReceiver广播给其它的应用程序,实现应用之间的通讯。

    **3.2.3 ******Service****

    Service是提供连续信息的应用程序。它是运行于应用程序后台的服务,在用户进行其它活动的时候,这个服务将一直运行在基于Android平台的即时通讯统的研究与实现后台直到用户停止该服务或服务运行结束。本系统客户端扩展功能的音乐播放就是采用Service来进行设计和开发的,使用户可以边聊天边听音乐。

    **3.2.4 ******ContentProvider****

    Content Provider应用程序能够将它们的数据保存到文件、SQL数据库和其它的存储设备中。当应用程序需要使用存储设备中的数据时,可以使用Content Provider来完成。使用Content Provider能够灵活的替换底层使用的存储设备,使开发者可以专著于应用逻辑的开发,不用考虑底层存储设备的细节,从而使应用系统具有良好的数据

    **4 ****** 需求分析****

    **4.1 ******业务流程图****

    [图片上传失败...(image-36e2dd-1555414018806)]

    image.gif ​ image image.gif

    **4.2 ******主要功能****

    [图片上传失败...(image-ee7c3b-1555414018806)]

    image.gif ​ image image.gif

    **5 ******系统设计与实现****

    **5.1 ******相关技术****

    **5.1.1 ******Http通信****

    HttpURLConnection接口

    首先需要明确的是,Http通信中的POST和GET请求方式的不同。GET可以获得静态页面,也可以把参数放在URL字符串后面,传递给服务器。而POST方法的参数是放在Http请求中。因此,在编程之前,应当首先明确使用的请求方法,然后再根据所使用的方式选择相应的编程方式。
    
    HttpURLConnection是继承于URLConnection类,二者都是抽象类。其对象主要通过URL的openConnection方法获得。创建方法如下代码所示:
    
    URL url = new URL("http://....");  
    
    HttpURLConnection urlConn=(HttpURLConnection)url.openConnection();
    
    image.gif

    **5.1.2 ******xml解析****

    <u><u>Android</u></u>平台上可以使用Simple API for XML(SAX)、Document Object Model(DOM)和Android附带的pull解析器解析XML文件。

    (1)使用SAX读取XML文件

    SAX是一个解析速度快并且占用内存少的XML解析器,非常适合用于Android等移动设备。SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。所谓事件,其实就是一些回调(callback)方法,这些方法(事件)定义在ContentHandler接口。

    下面是一些ContentHandler接口常用的方法:

    startDocument()当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。

    endDocument()和上面的方法相对应,当文档结束的时候,调用这个方法,可以在其中做一些善后的工作。
    startElement(String namespaceURI, String localName, String qName, Attributes atts)当读到一个开始标签的时候,会触发这个方法。namespaceURI就是命名空间,localName是不带命名空间前缀的标签名,qName是带命名空间前缀的标签名。通过atts可以得到所有的属性名和相应的值。要注意的是SAX中一个重要的特点就是它的流式处理,当遇到一个标签的时候,它并不会纪录下以前所碰到的标签,也就是说,在startElement()方法中,所有你所知道的信息,就是标签的名字和属性,至于标签的嵌套结构,上层标签的名字,是否有子元属等等其它与结构相关的信息,都是不得而知的,都需要你的程序来完成。这使得SAX在编程处理上没有DOM来得那么方便。
    endElement(String uri, String localName, String name)这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。
    characters(char[] ch, int start, int length)这个方法用来处理在XML文件中读到的内容,第一个参数用于存放文件的内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。

    (2)使用DOM读取XML文件

    除了可以使用 SAX解析XML文件,大家也可以使用熟悉的DOM来解析XML文件。 DOM解析XML文件时,会将XML文件的所有内容读取到内存中,然后允许您使用DOM API遍历XML树、检索所需的数据。使用DOM操作XML的代码看起来比较直观,并且,在某些方面比基于SAX的实现更加简单。但是,因为DOM需要将XML文件的所有内容读取到内存中,所以内存的消耗比较大,特别对于运行Android的移动设备来说,因为设备的资源比较宝贵,所以建议还是采用SAX来解析XML文件,当然,如果XML文件的内容比较小采用DOM是可行的。

    (3)使用Pull解析器读取XML文件

    除了可以使用 SAX和DOM解析XML文件,大家也可以使用Android内置的Pull解析器解析XML文件。 Pull解析器的运行方式与 SAX 解析器相似。它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。事件将作为数值代码被发送,因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法可以获取下一个Text类型元素的值

    **5.1.3 ******广播机制****

    BroadcastReceiver:他主要是实现了不同的应用程序之间数据的异步接收,其本质是一个事件监听器,用于监听系统全局的广播消息

    1.概念:

    1.1 Broadcast:是一种广泛运用的在应用程序之间传输信息的机制

    1.2 BroadcastReceiver:是对发送出来的 Broadcast进行过滤接受并响应的一类组件,其本质是一个监听器,用来监听系统全局的广播信息

    2.广播机制工作原理:

    如何发送Broadcast和使用BroadcastReceiver过滤接收:

    2.1 首先在需要发送信息的地方,把要发送的信息和用于过滤的信息(如Action、Category)装入一个Intent对象

    2.2 然后通过调用 Context.sendBroadcast()、sendOrderBroadcast()或sendStickyBroadcast()方法,把Intent对象以广播方式发送出去。

    2.3 当Intent发送以后,所有已经注册的BroadcastReceiver会检查注册时的IntentFilter是否与发送的Intent相匹配,若匹配则就会调用BroadcastReceiver的onReceive()方法

    3.注册BroadcastReceiver有两种方式:

    3.1 静态的在AndroidManifest.xml中用<receiver>标签声明注册,并在标签内用<intent-filter>标签设置过滤器

    3.2 动态的在代码中先定义并设置好一个 IntentFilter对象,然后在需要注册的地方调 Context.registerReceiver()方法,如果取消时就调用Context.unregisterReceiver()方法。如果用动 态方式注册的BroadcastReceiver的Context对象被销毁时, BroadcastReceiver,也就自动取消注册了,动态注册退出程序前要记得调用Context.unregisterReceiver()方法

    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(String);//BroadcastReceiver指定action,
    
    image.gif

    registerReceiver(BroadcastReceiver,intentFilter); (一般:在onStart中注册,onStop中取消unregisterReceiver;官方提醒,如果在Activity.onResume()里面注册了,就必须在Activity.onPause()注销)

    4.两种注册方式的区别:

    4.1 静态注册可以在xml里面一目了然,而动态注册方式,隐藏在代码中,比较难发现

    4.2 同一优先级的广播接收器,动态的要比静态注册接受的早

    sendBroadcast 发送的是无序广播

    sendOrderedBroadcast 发送的是有序广播

    5.指定接收的权限:

    若在使用sendBroadcast()的方法是指定了接收权限,则只有在AndroidManifest.xml中用<uses-permission>标签声明了拥有此权限的BroascastReceiver才会有可能接收到发送来的Broadcast

    6.实现一个广播接收器的步骤:

    6.1第一步:继承BroadcastReceiver,并重写onReceive()方法。

    public class IncomingSMSReceiver extends BroadcastReceiver{  
       @Override public void onReceive(Context context, Intent intent){ }  
    }  
    
    image.gif

    6.2 第二步:订阅感兴趣的广播Intent,订阅方法有两种:

    第一种:使用代码进行订阅

    IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");  
    IncomingSMSReceiver receiver = new IncomingSMSReceiver();  
    registerReceiver(receiver, filter);  
    
    image.gif

    第二种:在AndroidManifest.xml文件中的<application>节点里进行订阅:

    <receiver android:name=".IncomingSMSReceiver">  
         <intent-filter>  
              <action android:name="android.provider.Telephony.SMS_RECEIVED"/>  
         </intent-filter>  
    </receiver>  
    
    image.gif

    7.常见广播Intent:

    一个receiver可以接收多个action的,即可以有多个intent-filter,需要在onReceive里面对intent.getAction(action name)进行判断

    接受短信

    action:android.provider.Telephony.SMS_RECEIVED

     permission:android.permission.RECEIVE_SMS
    

    接收电池电量变化

    action:android.intent.action.BATTERY_CHANGED

    接收开机启动

    aciton:android.intent.action.BOOT_COMPLETED

    permission:andro.permission.RECEIVE_BOOT_COMPLETED

    8.广播接收器的生命周期:

    在Android中,程序的响应(Responsive)被活动管理器(Activity Manager)和窗口管理器(Window Manager)这两个系统服务所监视。当BroadcastReceiver的Receiver方法在10秒内没有执行完毕,Android会认为该程序无响应。所以在BroadcastReceiver里不能做一些比较 耗时的操作,否则会弹出ANR(Application No Response)的对话框。

    如果需要完成一项比较耗时的工作,应该通过Intent启动一个Service来完成,而不是启动一个新的线程来完成,因为BoradcastReveiver的生命周期非常短暂,有可能在子线程还没有执行完毕,BroadcastReceiver就提前退出了,这样在进程中没有任何的活动组件,系统在内存紧张的情况下优先结束该进程,导致BroadcastReceiver启动的子线程不能执行完成

    一个BroadcastReceiver,每接受一次就是产生一个新的接收器对象 对象只有在被调用onReceive(Context, Intent)的才有效的,当从该函数返回后,该对象就无效的了,结束生命周期     
    
    public class IncomingSMSReceiver extends BroadcastReceiver {   
        //发送Intent启动服务,由服务来完成比较耗时的操作  
        Intent service = new Intent(context, XxxService.class);  
        context.startService(service);  
    }   
    
    image.gif

    9.广播接收器分类:

    Normal Broadcast(普通广播):

    1.1 完全是异步的的,理论上可以在同一时刻被所有接收器所接受,传播效率高

    1.2 广播接收器无法将处理结果传递给下一个接收者

    1.3 广播接收器无法阻止广播信息的传播

    Ordered Broadcast(有序广播):

    1.1 可以按照广播接收器预先设置的优先级依次接受Broadcast(优先级声明在<IntentFilter...>的android:priority属性中,数越大优先级越高,取值范围在-1000~1000之间)

    1.2 广播接收器可以终止广播的传播(abortBroadcast()),一旦终止,后面的广播接收器将无法接收到广播消息,也无法接收广播接收器所传递的信息

    1.3 广播接收器可以将处理结果传递给下一个接收者(前提条件,广播没有终止)

    小结:没有终止广播信息和结果数据能接收,若终止广播信息和结果数据都不能接收

    setResultExtras(bundle);//将广播消息的处理结果存入结果对象

    abortBroadcast();//终止发送广播

    Bundle bundle = getResultExtras(true);//接收所传递的广播结果对象

    String first = bundle.getString("first");

    10.UI事件监听器机制和广播事件处理机制的联系与区别:

    联系:都是基于事件监听处理机制

    9.1 UI事件处理机制是程序组件级别的(比如:按钮的单击事件),而广播事件处理机制是系统级别的

    9.2 UI事件监听器的注册只能在代码中实现,而广播放事件的监听器可以在代码中注册也可以在xml配置文件里面注册

    9.3 UI事件监听器的处理和主程序是同步的,而是广播放事件的事件处理是异步的

    9.4 UI事件监听器监听的是程序中的对象,而广播放事件的监听器监听的事件源是Android应用中其他的组件

    **5.1.4 ******ListView布局 ****

    ListView 如果仅仅出于功能上的需求ListView可能没有存在的必要,ListView能作的事情基本上ScrollView也能胜任。ListView存在的最根本的原因在于它的高效(如何实现的?).ListView通过对象的复用从而减少内存的消耗,也减少了对象的创建从而也减少的cpu的消耗(在Androidk中创建View对象经常伴随着解析xml)。ListView的本质是一张bitmap(当然所有的控件文字等在屏幕上看到的最终都会变成bitmap),ListView会按照需求,根据Adapter提供的信息把需要的Item画出来显示在屏幕上,当屏幕滚动的时候会重新计算Item的位置并绘制出新的bitmap显示在屏幕上。这样听起来感觉可能不是很高效,但这样带的好处就是,每用为一第个Item 创建一个View对象,样式一样的对象可以共用一个View对象,减少了内存的消耗。而且ListView是事件驱动的,只有当需要的时候才会重新绘制,并且只会 绘制当前屏幕上所显示的Items.

    ListView 离不开Adapter,通常的作法创建一个类继承BaseAdapter,Override getCount()和getView()等方法。生成这个类的对象,调用ListView的setAdapter()与ListViw进行绑定。

    ListView会调用跟其绑定的Adapter的getCount()方法知道有多少个Item需要展示,然后循环调用getView(int position, View convertView, ViewGroup parent)知道第position个Item该怎么画,并画出来直到把当前的ListView的空间填满。当Adapter当中的数据改变时,需调用notifyDataSetChanged ()告诉Adapter数据发生了变化或者给Adapter注册一个观察者registerDataSetObserver (DataSetObserver observer)。当Adapter得知与其绑定的数据己发生改变时间,会再次调用getCount()方法,并循环调用getView(int position, View convertView, ViewGroup parent)刷新当前页面

    [图片上传失败...(image-80d611-1555414018806)]

    image.gif ​ image image.gif

    **5.1.5 ******GridView布局****

    a.需要创建GridView xml布局文件

    必须定义的属性(列数,列宽,对其方式),android:numColumns="auto_fit" android:columnWidth="90" android:gravity="center"

    b.创建数据适配器ImageAdapter(注意一定要给imageViewz赋值)

    if(convertView==null){
        //设置ImageView的资源
        ImageView imageView = new ImageView(mContent);
        //设置图片的尺寸
        imageView.setLayoutParams(new GridView.LayoutParams(85,85));
        //设置显示比例类型
        imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
    }else{
        imageView = (ImageView)convertView;
    }
    
    imageView.setImageResource(imgArr[position]);
    
    image.gif

    c.设置Activity的布局文件,并获得GriwView,并且设置它的适配器

    setContentView(R.layout.gridview);

    d.获取GridView控件

    GridView gv = (GridView)findViewById(R.id.gridView);

    e.设置GridView的匹配器

    gv.setAdapter(new ImageAdapter(this));

    f.设置网格元素的监听器

    gv.setOnItemClickListener(new AdapterView.onItemClickListener(){});

    **5.1.6 ******翻页技术****

    [图片上传失败...(image-46648f-1555414018806)]

    image.gif ​ image image.gif

    实现原理:

    使用贝赛尔曲线。曲线有四个点:起始点、终止点(也称锚点)以及两个相互分离的中间点。滑动两个中间点,贝塞尔曲线的形状会发生变化。

    根据第一种翻页效果原理可以确定a、e、h、f、g ,由eh平行于cj且af垂直于eh,则 af垂直于cj则三角形egf相似于三角形cnf 则有ef:cf = gf:nf 。

    设n为ag中点 则有cf=(3/2)*ef ,则c点坐标可求 由c点、k点坐标已知可知过两点间的直线

    由该直线可计算与y轴相交点j 由a、e、c、j可计算两条直线的相交点b 同理可求点k。

    在Android中的具体实现步骤:

    起始页展示

    1.创建屏幕尺寸的bmp 2.将图片转化为canvas 3.获取起始页面数据 3.在canvas中绘制起始页数据 4.在当前视图中复写onDraw进行重绘出bmp对象

    翻页处理

    1.初始化时创建两个bmp(bmp1、bmp2)并将其转换为canvas(canvas1、canvas2)

    2.获取手势首次触摸的区域 (例:当首次点击屏幕的位置x<50&&y<50则为左上角)

    3.根据首次点击区域判断需要展示的数据(例:首次点击处于左侧区域【左上、左下】的则判断操作为下一页操作)

    4.获取下一页中数据并绘制出来在canvas2中

    5.根据1中获取的区域位置调用起始动画使视图移动到手势首次点击位置

    6.获取手势每次移动的坐标并根据移动坐标计算绘制的各个点的坐标

    7.每次移动刷新视图

    **5.2 ******相关界面****

    **5.2.1 ******首页****

    [图片上传失败...(image-767cbb-1555414018806)]

    image.gif ​ image image.gif

    **5.2.2 ******报纸阅读页****

    [图片上传失败...(image-ceec97-1555414018805)]

    image.gif ​ image image.gif

    **5.2.3 ******报纸列表页****

    [图片上传失败...(image-8ac5ec-1555414018805)]

    image.gif ​ image image.gif

    **5.3 ******相关实现****

    **5.3.1 ******首页****

    Android的每一个可视化界面,都有其唯一的布局配置文件,该文件中有各种布局的方式,和各种资源文件如图像,文字,颜色引用等,程序在运行时可以通过代码对各个配置文件进行读取,这样可以形成不同的可视化界面和绚丽的效果。

    该软件的主界面是一个Activity,Android工程在启动每一个Activity时都会首先执行onCreate()方法,如下:

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    
    image.gif

    该方法主要执行界面的初始化操作,Activity有个设置布局的方法:

    setContentView(int id)
    
    image.gif

    最新报纸代码实现:

    paper = (Paper) bundle.getSerializable("paper");
    Bitmap bitmapZxbz = bundle.getParcelable("bitmapZxbz"); publishDateTv.setText(paper.getPublishDate().toString());
    paperSizeTv.setText(paper.getSize()+"");
    paperImgIv.setImageBitmap(bitmapZxbz);
    
    image.gif

    本期导读代码实现:

    listArticle = (List<Article>) bundle.getSerializable("listArticle");
    List<HashMap<String,String>> listArticleMap = new ArrayList<HashMap<String,String>>();
    
    LayoutParams params = bqddLv.getLayoutParams();    
    params.height = listArticle.size()*42;           
    bqddLv.setLayoutParams(params); 
    
     BqddArrayAdapter adapterBqdd = new BqddArrayAdapter(IndexActivity.this,R.layout.bqdd,listArticle);
     bqddLv.setAdapter(adapterBqdd);
     bqddLv.setOnItemClickListener(new BqddLvOnItemClickListener());
     bqddLv.setItemsCanFocus(true);   
    
    image.gif

    过往浏览代码实现:

    String[] picGwllArr = bundle.getStringArray("picGwllArr");
    gwllGridView.setAdapter(new GwllImageAdapter(IndexActivity.this,picGwllArr));
    
    image.gif

    翻页代码实现:

    BookLayout bk = new BookLayout(PaperReadActivity.this,listPage);
    BookAdapter ba = new BookAdapter(PaperReadActivity.this,pageArr,false);   
    bk.setPageAdapter(ba);
    setContentView(bk);
    
    image.gif

    **5.3.2 ******报纸阅读页****

    BookLayout bk = new BookLayout(PaperReadActivity.this,listPage);
    BookAdapter ba = new BookAdapter(PaperReadActivity.this,pageArr,false);
    bk.setPageAdapter(ba);
    setContentView(bk);
    
    image.gif

    **5.3.3 ******报纸列表页****

    private void InitLayout() {
    //得到ScrollView控件
    waterfall_scroll = (LazyScrollView) findViewById(R.id.waterfall_scroll);
    //的到ScrollView控件下的子控件
    waterfall_scroll.getView();
    //给ScrollView绑定滑屏监听器
    waterfall_scroll.setOnScrollListener(new OnScrollListener() {
    @Override
    public void onTop() {
    // 滚动到最顶端
    Log.d("LazyScroll", "Scroll to top");
    }
    
    @Override
    public void onScroll() {
    // 滚动中
    Log.d("LazyScroll", "Scroll");
    }
    
    @Override
    public void onBottom() {
    // 滚动到最低端 调用该方法
    AddItemToContainer(++current_page, page_count);
    }
    });
    
    //得到线性布局控件
    waterfall_container = (LinearLayout) this.findViewById(R.id.waterfall_container);
    //实例化线性布局控件集合
    waterfall_items = new ArrayList<LinearLayout>();
    //循环给线性控件集合赋值,并将子控件添加到父控件
    for (int i = 0; i < column_count; i++) {
    System.out.println("--------->"+i);
    LinearLayout itemLayout = new LinearLayout(this);
    LinearLayout.LayoutParams itemParam = new LinearLayout.LayoutParams(itemWidth, LayoutParams.WRAP_CONTENT);
    // itemParam.width = itemWidth;
    // itemParam.height = LayoutParams.WRAP_CONTENT;
    itemLayout.setPadding(2, 2, 2, 2);
    itemLayout.setOrientation(LinearLayout.VERTICAL);
    itemLayout.setLayoutParams(itemParam);
    waterfall_items.add(itemLayout);
    waterfall_container.addView(itemLayout);
    }
    
    
    image.gif

    **6 ******结论****

    通过对Android智能手机报系统的开发,对Android下Http网络通信机制有了深入的了解,熟悉了Android开发架构和API调用, 掌握了多线程开发技术,熟练Android平台UI布局,熟练常用控件使用,通过项目实践认识到整个开发过程中就是围绕着一个数据,Activity显示数据,Service处理数据,Intent传递数据,BroadcastReceiver接收数据,ContentProvider共享数据,对Adroid平台提供的几大基本组件有深刻的理解和认识

    Activity:是整个应用程序的门面,主要负责应用程序当中数据的展示,是各种各样控件的容器,是用户和应用程序之间交互的接口 (美女)

    Service:在前台不可见,但是承担大部分数据处理工作,Service和Activity的地位是并列的,他也代表一个单独的Android组件,区别在于:Activity运行与前台,Service通常位于后台运行,他一般需要与用户交互,因此Service没有图形用户界面,通常他为其他的组件提供后台服务或监控其他组件的运行状态(劳模)

    Intent:是应用程序种各个组件联系的桥梁,主要负责应用程序中所有数据的传递(运输大队长)

    BroadcastReceiver:他主要是实现了不同的应用程序之间数据的异步接收,其本质是一个事件监听器,用于监听系统全局的广播消息(广播接收器)

    ContentProvider:负责不同应用程序之间数据的共享,为不同的应用程序之间数据访问提供统一的接口 ,这个接口就是ContentHandler,具体就是要实现如下的四个抽象方法insert(),delete(),update(),query(),通常它与ContentResolver结合使用,一个是应用程序使用ContentProvider来暴露自己的数据,而另外一个是应用程序通过ContentResolver来访问数据(国家档案馆)

    相关文章

      网友评论

          本文标题:基于Android平台智能手机报系统的设计与开发

          本文链接:https://www.haomeiwen.com/subject/coeiwqtx.html