zoukankan      html  css  js  c++  java
  • Android应用程序开发疑问

    为什么android.util.log会提供五种不同级别的打印输出方式?(打印输出在Logcat窗口)比如:Log.v()用于打印比较琐碎的信息;Log.d()用于打印调试信息;Log.i()用于打印比较重要的数据信息;Log.w()用于打印一些警告信息,提示程序可能存在的潜在风险;Log.e()打印程序中错误信息。-->个人理解:可在应用程序中的任何地方使用以上五种不同的Log输出方式,但是建议“有目的和区分度”地使用,只有这样才能够方便使用其过滤功能,并能够分析程序的执行路径(在不同的路径使用不用的级别输出Log)。

    Android应用程序的AndroidManifest.xml文件,在注册activity时,使用的label标签指定活动(Activity)中标题栏内容。标题栏是显示在活动最顶的;此外,给主活动指定的label不仅会成为标题栏中的内容,还会成为启动器Launcher中应用显示的名称。

    活动Activity部分,总结:四种状态(针对于Activity存在于任务栈中的状态:运行状态、暂停状态、停止状态和销毁状态)、三种生存期(针对于生命周期而言:完整生存期、可见生存期和前台生存期)和七个回调方法(onCreate() onStart() onResume() onPause() onStop() onDestory() onRestart()),以及四种启动模式(Standard-->SingleTop-->SingleTask-->SingleInstance)。

    多个Activity之间传递值时,使用包名作为前缀(确保唯一性),例如: public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE";

    不要BroadcastReceiver的onReceive()中执行过多的逻辑或者进行任何的耗时操作,因为广播接受者中是不允许开启线程的,当onReceive()运行了较长时间而没有结束时,程序就会报错。广播接受者更多的是扮演一种打开程序其他组件的角色,比如创建一条状态栏通知,或者启动一个服务等。

    广播是一种跨进程的通信方式(应用程序能够接受系统广播)。

    正是由于广播机制是一种跨进程的通信方式,很有可能会导致程序的不安全性。为了解决广播的安全性问题,Android引入了一套本地广播机制,使用这个机制发出的广播只能够字应用程序内部进行传递,并且广播接受者也只能接收来自本应用程序发出的广播,这样所有的安全性问题就都不存在了。

    使用本地广播的几点优势:

    1. 明确地知道正在发送的广播不会离开我们的程序,不需要担心机密数据泄露;

    2. 其他程序无法将广播发送到我们的程序内部,不需要担心会有安全漏洞的隐患;

    3. 发送本地广播比起发送系统全局广播会带来更高效率。

    Android系统提供三种方式用于简单地实现数据持久化功能,即:文件存储、SharedPreference存储以及数据库存储。除了这三种方式之外,还可以将数据保存到手机的SD卡上,不过使用前三种方式相对简单,且比起存储到SD卡中会更加安全。

    文件存储方式:不对存储的内容进行任何的格式化处理,所有数据都是原封不动地保存到文件当中的,比较适合用于存储一些简单的文本信息或二进制数据。如果想使用文件存储的方式来保存一些复杂的文本数据,就需要定义一套自己的格式规范,方便以后将数据从文件中重新解析出来。

    Context类提供openFileOutput()用于将数据存储到指定的文件中,所有文件默认保存到/data/data/<packagename>/files/目录下。

    文件存储方式不适合用于保存一些较为复杂的文本数据。

    三种方式得到SharedPreferences实例:

    1. Context类中的getSharedPreferences()

        方法接收两个参数,前者为SharedPreferences文件名,后者为操作模式。SharedPreferences文件都是存放在/data/data/<packagename>/shared_prefs/目录下的。MODE_PRIVATE模式表示只有当前应用程序才可以对这个文件进行读写操作;MODE_MULTI_PROCESS模式(This constant was deprecated in API level 23.)一般用于会在多个进程中对同一个SharedPreferences文件读写。MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE两种模式:This constant was deprecated in API level 17. 官方已经不再推荐使用这种方式实现进程间的数据共享。而推荐使用更加安全可靠的内容提供器技术。

    2. Activity类中的getPreferences()

        使用这个方法时,会自动将当前的类名作为SharedPreferences文件名。

    3. PreferenceManager类中的getDefaultSharedPreferences()

        是一个静态方法,自动使用当前应用程序的包名作为前座来命名SharedPreferences文件。

    SharedPreferences文件是使用XML的格式来对数据进行管理的。

    SQLite数据库文件会存放到/data/data/<packagename>/databases/目录下。使用数据库存储数据,一般包含两个部分:数据库,以及存储在数据库中的表——table。

    如果想要使用adb工具,需要将adb tool所在的路径配置到系统环境变量中;如果需要操作数据库,首先进入到数据库所在的目录,然后输入:sqlite3 database_name。

    数据库操作支持事务处理,也就是让事务支持的业务逻辑执行完毕时才产生想要的效过,若中途崩溃,则退回到启动事务的起点。

    ContentProvider内容提供者可以选择只对哪一个部分数据进行共享,从而保证隐私数据的安全性。

    内容提供者一般有两种使用方式:一是使用现有的内容提供者来读取和操作相应程序的数据;二是创建自己的内容提供者给我们程序中的数据提供外部访问接口。

    Service:Android的后台运行功能,也就是说,应用程序即使在关闭的情况下仍然可以再后台继续运行;IOS是不支持后台的,当应用程序不在前台运行时就会进入到挂起状态。服务Service是Android中实现后台运行的解决方案,适合去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖于任何用户界面,即使当程序被切换到后台,或者用户打开了另一个应用程序,服务仍然能保持正常运行。

    需要注意的是,服务并不是运行在一个独立地应用程序中的,而是依赖于创建服务时所在的应用程序进程。当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。

    实际上服务并不会自动开启线程,所有代码都是默认运行在主线程中的。也就是说,我们需要在服务内部手动创建子线程,并在这里执行具体的任务,否则就有可能出现主线程被阻塞的的情况。

    Android的UI是线程不安全的。如果想要更新应用程序里的UI元素,则必须在主线程中进行,否则就会出现异常。如果确实需要在子线程执行耗时任务,然后根据任务的执行结果来更新相应的UI控件,该如何处理?

    Android中的异步和同步机制:Synchronous同步和Asynchronous异步的概念最初来自通信领域。通信同步指客户端在发出请求后,必须要在服务端有回应后客户端才继续发送其他请求,所有的请求都会在服务端得到同步,直到服务端发返回请求;通信异步指客户端在发送请求后,不必等待服务端的回应就可以发送下一个请求,对所有的请求动作来说将会在服务端得到异步,这条请求的链路就像是一个请求队列,所有的请求动作在这里都不会得到同步。

    异步消息处理机制解决子线程中进行UI操作的问题。Android中的异步消息处理主要有四个部分组成,Message(用于在不同线程之间交换数据,是在线程之间传递的消息)、Handler(主要用于发送和处理消息的)、MessageQueue(用于存放所有通过Handler发送的消息,每个线程都会有一个MessageQueue)和Looper(是每个线程中的MessageQueue的管家,每个线程只会有一个Looper对象)。

    另一个工具:AsyncTask,背后的实现原理也是基于异步消息处理机制,只是Android进行了封装。

    停止Service的方式:在Activity中决定服务何时启动和停止,startService()和stopService()用于服务的启动和停止。此外,在服务中调用自己的stopSelf()可以实现服务的停止。

    活动和服务的通信:在活动中指挥服务去干什么,服务就去干什么;通过bindService()实现活动和服务的交互。

    服务中的代码默认运行在主线程中,如果直接在服务里去处理一些耗时的逻辑,就很容易出现ANR。因此,需要在服务中创建子线程,然后在这里去处理那些耗时的逻辑。一般是在onStartCommand()中创建并开启子线程,并在其中调用stopSelf()停止服务。

    Android专门提供了IntentService(),用于解决上述的两个步骤。复写onHandleIntent(),并在其中执行耗时操作,因为这个方法中的内容会在子线程中执行,而不必担心ANR的问题。在执行完上述方法后,会自动结束去执行onDestory()。上述IntentService实例集开启线程和自动停止于一身。

    实践P376 中的定时任务。

    使用Intent实例传递自定义对象,必要条件:自定义类必须实现Serializable或者Parcelable接口。不同之处在于:前者是将对象进行序列化,后者则将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型。虽然后者在实现上会显得复杂,但效率会更好,所以推荐使用后者。

    编写测试用例,创建测试工程,进行单元测试,实践P468的单元测试功能。

  • 相关阅读:
    区别@ControllerAdvice 和@RestControllerAdvice
    Cannot determine embedded database driver class for database type NONE
    使用HttpClient 发送 GET、POST、PUT、Delete请求及文件上传
    Markdown语法笔记
    Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required
    Mysql 查看连接数,状态 最大并发数(赞)
    OncePerRequestFilter的作用
    java连接MySql数据库 zeroDateTimeBehavior
    Intellij IDEA 安装lombok及使用详解
    ps -ef |grep xxx 输出的具体含义
  • 原文地址:https://www.cnblogs.com/CVstyle/p/6345144.html
Copyright © 2011-2022 走看看