Android编程权威指南总结(二)

第五章     第二个activity

一、Android Tools属性

<TextView 
 android:id="@+id/answer_text_view" 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content" 
 android:padding="24dp" 
 tools:text="Answer"/>

1、介绍

注意这个TextView组件,它的 tools 和 tools:text 属性的命名空间比较特别。该命名空间可以覆盖某个组件的任何属性。这样,就可以在Android Studio预览中看到效果。TextView有 text 属性,可以为它提供初始值,因而在应用运行前就知道它大概的样子。而在应用运行时,Answer 文字不会显示出来。

2、具体解释和使用

(1)解释

我们写的UI效果很多时候需要提前预览,我们一般的做法是这样的:比如像ImageView、TextView这种基础控件,我们会添加android:text="xxx" 和 android:src="@drawable/xxx" 这种属性去进行测试和预览,而这些数据多了之后,很有可能遇到:测试的时候某些地方出现了本不该出现的数据,也就是某些测试数据未删除的情况。

所以我们会想:有没有一种方法既能预览数据又能在真实运行的时候移除这些无关的数据?

而 Android 的 Tools Attributes 就可以实现这个效果。

(2)使用

https://www.cnblogs.com/moosphon/p/11565829.html#3222832688

这里面有详细介绍,我觉得挺好(这地址是人家的帖子,不是我的~~~)

 

第六章     Android SDK版本与兼容

一、Android SDK版本

1、SDK最低版本(minSdkVersion)

以最低版本设置值为标准,操作系统会拒绝将应用安装在系统版本低于标准的设备上。

2、SDK目标版本(targetSdkVersion)

目标版本的设定告诉Android:应用是为哪个API级别设计的。大多数情况下,目标版本即最新发布的Android版本。

什么时候需要降低SDK目标版本呢?新发布的SDK版本会改变应用在设备上的显示方式,甚至连操作系统后台运行行为都会受影响。如果应用已经开发完成,应该确认它在新版本上能否正常运行,根据测试结果,要么修改应用以适应新版本系统,要么降低SDK目标版本。

降低SDK目标版本可以保证的是,即便在高于目标版本的设备上,应用仍然可以正常运行,且运行行为和目标版本保持一致,这是因为新发布版本中的变化已被忽略。

3、SDK编译版本(compileSdkVersion)

SDK最低版本和目标版本会通知操作系统,而SDK编译版本只是你和编译器之间的私有信息。

在编译代码时,SDK编译版本(即编译目标)指定具体要使用的系统版本。Android Studio在寻找类包导入语句中的类和方法时,编译目标确定具体的基准系统版本。

编译目标的最佳选择为最新的API级别,当然,需要的话也可以改变应用的编译目标。例如,Android新版本发布时,可能就需要更新编译目标,以便使用新版本引入的方法和类。

4、安全添加新版本API中的代码

SDK最低版本和编译版本之间差异太大,由此会带来兼容性问题。比如:最低版本为API 19,编译版本为API 21,那如果调用了API 21的代码而API 19中没有这个代码的话会怎样呢?结果显示如果在API 19 设备上安装,程序会崩溃。

随着Android lint的精进,现在在老版本系统上调用新版本代码时,Android lint会告警提示,如果没有看到提示,就选择Analyze——>Inspect Code...菜单项手动触发lint。

因为SDK编译版本为API 21,编译器本身编译代码没有问题,而Android lint知道项目SDK最低版本,所以及时指出了问题,这个告警信息你可以忽略,但是运行的时候就可能会崩溃,所以最好还是消除这些错误信息。一种方法是提升SDK最低版本到21,但是这种方法只是回避了兼容问题,应用不能在低于API 21的设备上安装了,自然就没有刚才提到的兼容问题了,但是这实际上并没有解决兼容问题;比较好的做法是在代码中判断Android设备版本,

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    //如果设备API高于LOLLIPOP,就可以做一些操作
}else{
    //如果没有,就需要避免使用高版本API中才有的方法
}

5、Android开发文档

文档主页是 http://developer.android.com/ 。文档分为三大部分,即设计 开发 发布
 

Android文档可脱机查看,浏览SDK安装文件所在目录,找到 docs 目录,该目录包含了全部的Android开发者文档内容。

 

第七章      UI  fragment与 fragment 管理器

一、Gradle中添加依赖包

添加依赖包的示例:

compile 'com.android.support:appcompat-v7:26.0.1'

这个依赖项字符串使用了Maven坐标模式:groupId:artifactId:version。(Maven是一个依赖包管理工具,详见其官方网站:https://maven.apache.org/ )。

groupId,通常是类库的基础包名,能唯一标识Maven仓库中的依赖类库,就像上面的com.android.support

artifactId,是包中的特定库名,这里就是指 appcompat-v7

version,是指类库的版本号

二、fragment的生命周期

三、Activity中添加fragment

1、activity添加fragment的方式

activity托管fragment有两种方式:

  • 在activity布局中添加fragment
  • 在activity代码中添加fragment

第一种方式就是使用布局fragment。这种方式简单但是不够灵活。在activity布局中添加fragment,就等同于将fragment及其视图绑定在一起,并且在activity的生命周期过程中,无法替换fragment视图。

第二种方式比较复杂,但也是能够动态控制fragment的唯一方式。何时添加fragment以及随后可以完成何种具体任务由你定;也可以移除fragment、替换fragment、重新添加已移除的fragment等。

2、fragment事务

FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().add(R.id.fragment_container,fragment).commit();

 fragment事务被用来添加、移除、附加、分离或替换fragment队列中的fragment。这是使用fragment动态组装和重新组装用户界面的关键。FragmentManager管理着fragment事务回退栈。

 

第八章     使用RecyclerView显示列表

一、RecyclerView的优势

Android操作系统核心库包含ListView、GridView、Adapter这三个类。Android 5.0之前,创建列表项和网格项都应该优先使用这些类。

这些类的API与RecyclerView的API非常相似。ListView和GridView不关心具体的展示项,只负责展示项的滚动,Adapter负责创建列表项的所有视图,不过使用ListView和GridView时不一定非要使用ViewHolder模式(虽然可以并且应该使用)。

过去传统的实现方式现已被RecyclerView的实现方式取代,因此不用再费力的调整ListView和GridView的工作行为了。

举例来说,ListView API不支持创建水平滚动的ListView,因此需要很多额外的定制工作。使用RecyclerView时,虽然创建定制布局和滚动行为也需要额外的工作,但RecyclerView天生支持拓展,所以使用体验很好。

此外,RecyclerView还有支持列表项动画效果的优点。如果要让ListViewGridView支持添加和删除列表项的动画效果,实现起来既复杂又容易出错;而对于天生支持动画特效的RecyclerView来说,对付这些任务简直是小菜一碟。

二、使用单例的优缺点

Android开发实践中,经常会用到单例模式。然而单例如果使用不当,会导致应用难以维护,因此它也常遭人诟病。

Android开发常用到单例的一大原因是,它们比 fragment 或 activity 活得久。例如,在设备旋转或是在 fragment 或 activity间跳转的场景下,单例却不会受到影响,而旧的 fragment 或 activity 已经不存在了。

1、单例的优点

单例能方便地存储和控制模型对象。假设一个模型类DataBean,在一个比较复杂的应用中,它的许多个fragment和activity都会修改DataBean的数据,某个控制单元修改了DataBean的数据之后,怎么保证发送给其他控制单元的是最新数据呢?如果创建一个单例类来控制数据对象 DataBean,所有的修改都由它来处理,是不是控制数据的一致性就容易多了?而且,在控制单元间流转时,还可以给每个 dataBean 添加 ID 表示,让控制单元使用 ID 标识从单例类中获取完整的 dataBean 数据。

2、单例的缺点

虽然单例能存储数据,活的也比控制单元长,但并不代表它能永存。在我们切换至其他应用,或逢Android回收内存时,单例连同那些实例变量也就不复存在了。结论很明显:单例无法做到持久存储。(将文件写入磁盘或者发送到web服务器是不错的数据持久化存储方案)。

单例还不利于单元测试。

使用单例很方便,因而它很容易被滥用。在想用就用、想存就存之前,希望能深思熟虑:数据究竟用在哪里?用在哪里能真正解决问题?

这里讲的这些只是从本书上看来的,并不详细,如果想要详细了解,可以自行去查找详细解析。

 

第九章     使用布局与组件创建用户界面

一、日期格式化

public String StringData() {
        final Calendar c = Calendar.getInstance();
        c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
        String mYear = String.valueOf(c.get(Calendar.YEAR)); // 获取当前年份
        String mMonth = String.valueOf(c.get(Calendar.MONTH) + 1);// 获取当前月份
        String mDay = String.valueOf(c.get(Calendar.DAY_OF_MONTH));// 获取当前月份的日期号码
        String mHour = String.valueOf(c.get(Calendar.HOUR_OF_DAY));//获得当前小时
        String mMinute = String.valueOf(c.get(Calendar.MINUTE));//获得当前分钟
        String mSecond = String.valueOf(c.get(Calendar.SECOND));//获得当前秒

        String mWay = String.valueOf(c.get(Calendar.DAY_OF_WEEK));
        if ("1".equals(mWay)) {
            mWay = "天";
        } else if ("2".equals(mWay)) {
            mWay = "一";
        } else if ("3".equals(mWay)) {
            mWay = "二";
        } else if ("4".equals(mWay)) {
            mWay = "三";
        } else if ("5".equals(mWay)) {
            mWay = "四";
        } else if ("6".equals(mWay)) {
            mWay = "五";
        } else if ("7".equals(mWay)) {
            mWay = "六";
        }
        return mYear + "年" + mMonth + "月" + mDay + "日" + mHour + "时" + mMinute + "分" +         
                                                        mSecond + "秒" + "/星期" + mWay;
    }

第十章     使用 fragment  argument

一、fragment 获取数据的方式

fragment 有两种方式获取 intent 中的数据,一种简单直接,另一种复杂但比较灵活。

1、简单方式的使用和其缺点

(1)使用

直接使用 getActivity() 方法获取 Activity 的 intent,比如:

UUID crimeId = (UUID) getActivity().getIntent()
     .getSerializableExtra(CrimeActivity.EXTRA_CRIME_ID);

这种方式,除了 getActivity() 方法的调用,获取 extra 数据的实现代码与 activity 里获取 extra 数据的代码一样。 

 (2)缺点

这种方法破坏了fragment的封装。使用此方法的Fragment不再是可复用的构建单元,调用了getActivity() 之后就代表它现在由某个特定的Activity托管着,该特定Activity的 Intent 又定义了名为 EXTRA_CRIME_ID 的extra。这就意味着当前Fragment便再也无法用于其他Activity了。

2、复杂方法

一个比较好的做法是,将 extra 数据存储在Fragment的“某个地方”,而不是保存在Activity的私有空间里,这样就无需依赖Activity的Intent内的extra,Fragment就能获取自己所需的extra数据。“某个地方”就是fragment的 argument bundle。

每个fragment的实例都可附带一个Bundle对象,Bundle对象包含键--值对,一个键值对即一个argument。

要附加 argument bundle 给fragment,需要调用fragment.setArguments(Bundle)方法,而且,必须在fragment创建后、添加给activity前完成。

Android开发人员采取的习惯性做法:

在Fragment类中,编写可以接受UUID参数的newInstance(UUID)方法,创建 argument bundle 和 fragment 实例,然后附加 argument 给 fragment:

    private static final String ARG_CRIME_ID = "crime_id";

    public static CrimeFragment newInstance(UUID crimeId){
        Bundle args = new Bundle();
        args.putSerializable(ARG_CRIME_ID,crimeId);

        CrimeFragment fragment = new CrimeFragment();
        fragment.setArguments(args);
        return fragment;
    }

创建Fragment时,其托管的Activity应调用CrimeFragment.newInstance(UUID)方法,并传入从它的extra中获取的UUID参数值: 

 
    /**
     *这个方法是Activity超类的抽象方法,在每个Activity子类实现该方法,此方法代码是在托管Fragmen的           
     *Activity中实现的
     */
    @Override
    protected Fragment createFragment() {

        UUID crimeId = (UUID) getIntent().getSerializableExtra(EXTRA_CRIME_ID);
        return CrimeFragment.newInstance(crimeId);
    }

获取 argument:

UUID crimeId = (UUID) getArguments().getSerializable(ARG_CRIME_ID);

注意,Activity和Fragment不需要也无法同时相互保持独立, Activity必须了解Fragment的内部细节,以便托管fragment,但fragment不一定需要知道其托管Activity的细节,至少在需要保持fragment通用独立的时候如此。

二、为何要使用 fragment argument

fragment argument 的使用有点复杂,为什么不直接创建实例变量或者通过构造方法传递参数?

创建实例变量的方式并不可靠。因为操作系统在重建fragment时(设备配置发生改变),用户暂时离开当前应用(操作系统按需回收内存),任何实例变量都将不存在。

通过构造方法传递参数也是有隐患的。根据Android文档说明,当一个Fragment重新创建的时候,系统会再次调用Fragment中的默认构造函数,注意是默认构造函数。即,当你创建了一个带有参数的Fragment的之后,一旦由于什么原因(例如横竖屏切换)导致你的Fragment重新创建。那么,很遗憾,你之前传递的参数都不见了,因为recreate你的Fragment的时候,调用的是默认构造函数。因此,官方推荐使用Fragment.setArguments(Bundle bundle)这种方式来传递参数,而不推荐通过构造方法直接来传递参数。

因此,可以使,fragment argument 就是为应对上述场景而生。

还有一种方法应对上述场景:使用实力状态保存机制。就是将Crime ID 赋值给实例变量,然后在onSaveInstanceState(Bundle)方法中保存下来。但是这种方法维护成本比较高,比如:如果你在若干年后要修改fragment代码以添加其他argument,很可能会忘记在onSaveInstanceState(Bundle)方法里保存新增的argument

 

第十一章     使用ViewPager

一、FragmentStatePagerAdapter 与 FragmentPagerAdapter

    FragmentManager fragmentManager = getSupportFragmentManager();
    mViewPager.setAdapter(new FragmentStatePagerAdapter(fragmentManager) {
        @Override
        public Fragment getItem(int position) {
            Crime crime = mCrimes.get(position);
            return CrimeFragment.newInstance(crime.getId());
        }

        @Override
        public int getCount() {
            return mCrimes.size();
        }
    });

FragmentPagerAdapter 用法和 FragmentStatePagerAdapter 基本一致。唯一的区别在于,卸载不再需要的Fragment时,各自采用的处理方法有所不同。

FragmentStatePagerAdapter 会销毁不需要的 Fragment。事务提交后,Activity的 FragmentManager 中的Fragment会被彻底移除。FragmentStatePagerAdapter 类名中的“State”表明:在销毁Fragment时,可在 onSaveInstanceState(Bundle) 方法中保存Fragment的 Bundle 信息,用户切换回来时,保存的实例状态可用来生成新的Fragment。

 相比之下,FragmentPagerAdapter 有不同的做法,对于不再需要的Fragment,FragmentPagerAdapter 会选择调用事务的detach(Fragment) 方法来处理它,而非 remove(Fragment) 方法。也就是说,FragmentPagerAdapter 只是销毁了Fragment的视图,而Fragment实例还保存在FragmentManager中。因此,FragmentPagerAdapter 创建的Fragment永远不会被销毁。

 选择哪种adapter取决于应用的需求。通常来说,使用FragmentStatePagerAdapter 更节省内存。如果用户界面只需要少量的固定的Fragment,则FragmentPagerAdapter 是安全、合适的选择。最常见的例子就是使用 Tab 选项页显示用户界面。此外,将Fragment保存在内存中,更易于管理控制器层的代码。对于这种类型的用户界面,每个Activity通常只需两三个Fragment,基本不用担心内存不足的危险。

二、深入学习:ViewPager的工作原理

什么时候需要实现PagerAdapter接口?

需要ViewPager托管非Fragment视图时,就需要实现原生PagerAdapter接口。

三、深入学习:以代码的方式创建视图

以代码的方式创建视图很简单:调用视图类的构造方法,并传入Context参数。不创建任何布局文件,用代码就能创建完整的视图层级结构。

但是,最好不要这样做。下面就来说说使用布局文件的好处:

布局文件能很好地分离控制器层和视图层对象:视图定义在XML布局文件中,控制器层对象定义在Java代码中。这样,假设控制器层有代码修改的话,代码变更管理相对容易很多;反之亦然。

另外,使用布局文件,我们还能使用Android的资源适配系统,实现按设备属性自动调用合适的布局文件(就像之前说过的横屏模式的布局文件)。

当然,布局文件也不是毫无缺点。如果应用只需一个视图,估计没人愿意麻烦地创建并实例化布局XML文件。

除此之外,创建布局文件的缺点都不值得一提。

 

 

 
 
 
 
 
 
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值