添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
细心的南瓜  ·  Android ...·  6 天前    · 
粗眉毛的风衣  ·  uni-app x·  4 天前    · 
憨厚的大脸猫  ·  virtualbox 被召者 RC: ...·  2 月前    · 
酷酷的排球  ·  老酒馆_百度百科·  9 月前    · 
冷静的乌冬面  ·  李晨新剧将收官 ...·  11 月前    · 

Android提供了一个Application类,每当应用程序启动的时候,系统就会自动将这个类进行初始化。如果我们想要在任何地方轻松获取Context,可以自己定制一个Application类,方便管理程序内的一些全局状态信息。

首先创建一个MyApplication类继承自Application:

class MyApplication: Application() {
    companion object{
        lateinit var context: Context
    override fun onCreate() {
        super.onCreate()
        context = applicationContext

我们先定义了一个context变量,然后重写了onCreate()方法,并调用getApplicationContext()方法的返回值赋给context变量,这样我们就可以以静态变量的形式获取Context对象了。

注意:将Context设置成静态变量很容易造成内存泄漏的问题,所以Android studio会提示有风险。实际上这里获取的并不是Activity或Service中的Context,而是Application中的Context,它全局只会存在一份实例,并且在整个应用程序的生命周期内都不会回收,因此是不存在内存泄漏的风险的。

我们可以Alt+Enter使用注解,让AS忽略警告:

    companion object{
        @SuppressLint("StaticFieldLeak")
        lateinit var context: Context

此外,我们还需要告诉系统,当程序启动的时候应该初始化MyApplication类,而不是Application类。所以去到AndroidManifest.xml文件的标签下:

<application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.JetpackTest">
    </application>

此时,在任何地方都可以调用MyApplication.context获取Context了。

2.使用Intent传递对象

我们在使用Intent传递数据的时候,putExtra()方法中所支持的数据类型是有限的,如果想要传递一些自定义对象就比较困难。这里就学习一下如何使用Intent来传递对象,有两种方式:Serializable和Parcelable。

2.1 Serializable方式

Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。我们只需要让一个类去实现Serializable接口即可。

比如有一个Person类,包含name和age字段,想要序列化它,如下:

class Person : Serializable {
    var name = ""
    var age = 0

此时,所有的Person对象都可以序列化了。

在MainActivity中只需要这样写:

        val person = Person()
        person.name = "shuFu"
        person.age = 23
        val intent = Intent(this, SecondActivity::class.java)
        intent.putExtra("person_data", person)
        startActivity(intent)

然后在SecondActivity中获取这个对象,写法如下:

val person = intent.getSerializableExtra("person_data") as Person

操作很简单。

注意:这种传递对象的工作原理是先将一个对象序列化成可存储或可传输的状态,传递给另外一个Activity后再将其反序列化成一个新的对象。虽然这两个对象中存储的数据完全一致,但是它们实际上是不同的对象。

2.2 Parcelable方式

Parcelable也是实现相同的效果,不过它的原理是将一个完整的对象进行分解,分解后的每一部分都是Intent所支持的数据类型,这样就实现了传递对象的功能。

首先修改Person类中的代码:

class Person : Parcelable {
    var name = ""
    var age = 0
    override fun describeContents(): Int {
        return 0
    override fun writeToParcel(p0: Parcel, p1: Int) {
        p0.writeString(name)   //写出name
        p0.writeInt(age)   //写出age
    companion object CREATOR : Parcelable.Creator<Person> {
        override fun createFromParcel(p0: Parcel): Person {
            val person = Person()
            person.name = p0.readString() ?: ""    //读取name
            person.age = p0.readInt()              //读取age
            return person
        override fun newArray(p0: Int): Array<Person?> {
            return arrayOfNulls(p0)

首先实现Parcelable接口,重写describeContents()和writeToParcel()两个方法,第一个方法返回0即可,第二个方法需要调用Parcel的writeXxx()方法将Person类中的字段一一写出。然后还必须为Person类提供一个CREATOR的匿名类实现,这里创建了一个Parcelable.Creator接口的一个实现,泛型为Person。

然后再重写createFromParcel()和newArray()两个方法,第一个方法中需要创建一个Person对象并返回,同时要读取写出的字段,读取顺序一定要与写出顺序一致。第二个方法只需要调用arrayOfNulls()方法,并使用参数中传入的size作为数组大小,创建一个空的Person数组即可。

接着在MainActivity中的用法一样,只是要修改SecondActivity中的获取方式:

val person = intent.getParcelableExtra<Person>("person_data")

这种写法还是复杂,不过Kotlin提供了一种简便的用法,前提是要传递的所有数据都必须封装在对象的主构造函数中。

修改Person类:

@Parcelize
class Person(var name: String, var age: Int) : Parcelable{

只要把字段移到主构造函数中,然后添加注解即可。

3.定制自己的日志工具

如果我们在编程一个项目,期间为了方便调试,在很多地方都进行了打印日志,但是到了项目完成上线的时候,那些日志仍会打印,就会产生一些风险,但如果自己一行一行地去删,也显得太麻烦了。所以就需要做到能够控制日志的打印。项目开发时就打印,上线后就屏蔽掉。

接下来就定制一个日志工具,新建一个LogUtil单例类:

object LogUtil {
    private const val VERBOSE = 1
    private const val DEBUG = 2
    private const val INFO = 3
    private const val WARN = 4
    private const val ERROR = 5
    private var level = VERBOSE
    fun v(tag: String, msg: String) {
        if (level <= VERBOSE) {
            Log.v(tag, msg)
    fun d(tag: String, msg: String) {
        if (level <= DEBUG) {
            Log.d(tag, msg)
    fun i(tag: String, msg: String) {
        if (level <= INFO) {
            Log.i(tag, msg)
    fun w(tag: String, msg: String) {
        if (level <= WARN) {
            Log.w(tag, msg)
    fun e(tag: String, msg: String) {
        if (level <= ERROR) {
            Log.e(tag, msg)

这段代码清晰易懂。使用的时候就和普通日志一样:

 LogUtil.v("tag", "verbose")

只需要通过修改level变量的值,就可以自由地控制日志的打印。比如让level等于VERBOSE就可以把所有的日志都打印出来,让level等于ERROR就可以只打印程序的错误日志。使用了这种方法,在开发阶段将level指定成VERBOSE,当项目正式上线的时候将level指定成ERROR就可以了。

4.调试Android程序

学习一下如何让程序随时进入调试模式,先正常启动程序,进行一些操作之后,需要开始调试的时候,点击AS顶部工具栏的“AttachDebugger to Android Process”按钮,会弹出一个进程选择框,选择我们当前程序的进程,就会进入调试状态了。

5.深色主题

想要实现最佳的深色主题效果,应该针对每一个界面都进行浅色和深色两种主题的界面设计。不过我们还是有技巧的。

我们现在是有一个DayNight主题的,表示当用户在系统中开启深色主题时,应用程序会自动使用深色主题,反之就是浅色主题。新建项目时是自动应用了这个主题的,可以看到style.xml中的代码:

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.MaterialTest" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    </style>
</resources>

不过运行程序,开启深色主题的效果如下:


效果还是不错,只可惜标题栏和悬浮按钮没有变化,原因是它们使用的是定义在colors.xml文件中的颜色值,如下:

<resources>
    <color name="purple_200">#FFBB86FC</color>
    <color name="purple_500">#FF6200EE</color>
    <color name="purple_700">#FF3700B3</color>
</resources>

这种指定颜色值的引用方式相当于对控件颜色的硬编码,DayNight主题是不能对这些颜色动态转换的。

解决办法呢就是进行主题差异性编程,在values-night目录下新建一个colors.xml文件,在里面指定深色主题下颜色值:

<resources>
    <color name="purple_200">#303030</color>
    <color name="purple_500">#232323</color>
    <color name="purple_700">#343737</color>
</resources>

这些颜色的name要统一,因为第一个colors.xml文件中使用的是这种命名方式,所以我直接复制过来就只更改了颜色值。结果如下:

效果还是不错的,使用主题差异性编程几乎可以解决所有的适配问题,但是在DatNight主题下,最好还是尽量减少硬编码的方式来指定控件颜色。而是应该更多地使用能够根据当前主题自动切换颜色的主题属性。

比如说黑字应该衬托在白色的背景下,反之白字通常应该衬托在黑色的背景下,那么此时可以使用主题属性来指定背景以及文字的颜色,写法如下:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?android:attr/colorBackground">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="hello world"
        android:textSize="42sp"
        android:textColor="?android:attr/textColorPrimary" />
</FrameLayout>

这些主题属性会自动根据系统当前的主题模式选择最合适的颜色来呈现。

如果需要在不同主题下执行不同的代码,使用的时候就判断一下当前系统是否为深色主题:

    fun isDarkTheme(context: Context): Boolean {
        val flag = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
        return flag == Configuration.UI_MODE_NIGHT_YES

Kotlin是取消了按位运算符的写法的,改成了英文关键字,比如and关键字就对应了Java中的&运算符,or关键字对应|运算符,xor关键字对应^运算符。

原文链接:
https://www.cnblogs.com/imnotGemini/p/16023706.html 学习模拟电路分四步:     首先一定要先把分立元器件学好,学透。比如:电阻、电容、二极管、稳压管、三极管、比较器、运放、MOSFET等。分立元器件在模拟电路中是基本也是的组成部分。这好比人的组织细胞,要研究人就要先研究组织细胞。     其次,需要懂得利用这些分立器件的工作特性和条件来组成一个小的单元电路,学会让这个单元电路正常工作。这就好比各个组织细胞组成了人体的各个器官,模拟电路的各个单元电路正常高效工作就好比人体器官的正常健康;上海雷卯电子     再次,学会将各个单元电路有机地协调运转,联调可靠运行,这就好比各个器官的协调运动组成了一个健康充满活力的有生命的人。 今天给大家带来《android应用开发全程实录》中关于listview和adatper中的部分。包括listview的基本使用,listview的优化等。我们经常会在应用程序中使用列表的形式来展现一些内容,所以学好ListView是非常必需的。ListView也是Android中比较难以使用的控件,这节内容就将详细解读ListView的用法。一个ListView通常有两个职责(1)将数据填充到布局。(2)处理用户的选择点击等操作。第一点很好理解,ListView就是实现这个功能的。第二点也不难做到,在后面的学习中读者会发现,这非常简单。一个ListView的创建需要3个元素。(1)ListVi 不过,虽然你已经储备了足够多的知识,并掌握了很多的最佳实践技巧,但是你还从来没有 真正开发过一个完整的项目,也许在将所有学到的知识混合到一起使用的时候,你会感到有些手 足无措。这种调试方式虽然完全可以正常工作,但在调试模式下,程序的运行效率将会大大地降低, 如果你的断点加在一个比较靠后的位置,需要执行很多的操作才能运行到这个断点,那么前面这 些操作就都会有一些卡顿的感觉。方法中所支持的数据类型是有限的,虽然常用的一 些数据类型它都会支持,但是当你去传递一些自定义对象的时候,就会发现无从下手。 回顾一下自己这段时间的经历,因公司突然通知裁员,我匆匆忙忙地出去面了几家,但最终都没有拿到offer,我感觉今年的寒冬有点冷。公司开始第二波裁员,我决定主动拿赔偿走人。后续的面试过程我做了一些准备,基本都能走到hr面,后面我也顺利地拿到了offer,我给大家分享下我的求职体会,希望能给大家一些参考。 1.【字节跳动全套高级学习资料】九大专题: 1.高级UI,自定义View UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。 不过很显然现在远远 android开发高级技巧 到目前为止,这些是我个人在Android开发方面的经验。 提示的数量实际上是十个,因此我可以将其称为“ Android开发的十个提示 ”,但我认为已经有足够多的文章具有这个醒目的标题。 这让我起已故喜剧演员乔治·卡林(George Carlin): 我对十诫有疑问。 这就是:为什么有十个?…为什么不九个或十一个呢? 我告诉你为什么。 因为十听起来很重要。 十声... 1.打开手机拨号界面,输入:“*#*#2846579#*#*”[感谢室友小马提示,使用HTML转义字符表示*] 2.进入工程菜单——&gt;后台设置——&gt;LOG设置——... 一、全局获取Context Android提供了一个Application类,每当程序启动的时候,系统会自动将这个类进行初始化。可以定制一个自己的Application类,便于管理程序内的一些全局状态信息,如Context。 新建类继承Application,设置私有静态全局变量context 重写其onCreate()方法,在其中用getApplicationContext()为context赋值 提供一个getContext()方法,将刚才获取的Context进行返回 在AndroidManifest 定义一个MyApp类,继承Application public class MyApplication extends Application { private static Context context; @Override public void onCreate() { context = getApplicationContext(); public static ContentProvider, AIDL. Messenger. BroadcastReceiver .Intent8网络通信 8.网络通信 http ( java )socket ( java )websocket(java) 五、高级 9.多.. 「Android」开发小技巧合集沉浸式标题栏修改主题样式颜色隐藏标题栏进行自主设置状态栏设置代码圆型图片设置APP图标修改APP名称创建不同分辨率图片文件夹更改项目名称Button字母大小写TextView 字体样式EditText 输入时调用数字键盘CheckBox变为圆形自定义Switch样式原生样式与自定义样式对比设计选择器滑块和轨道样式导入不同gradle版本的项目日期相关处理获取系统时间将毫秒转为时间字符串将日期字符串毫秒复用布局文件GenyMotion模拟器 沉浸式标题栏 在我们日常开发中,常常