使用 DataBinding 精简代码

在构建布局的时候,是不是感到要写很多的 findViewById 很浪费时间呢?尤其是布局文件变化的时候,也要在 Activity 中更改很多内容,极大的降低了开发效率,而谷歌在 JetPack 中提供了一种十分有效的方法来精简代码结构,提升开发效率,那就是 DataBinding 下面来介绍 DataBinding 的使用 用到的依赖 implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' 开启 dataBinding 在 app 的 build.gradle 文件中添加以下内容 dataBinding { enabled true } 位置参考 android { compileSdkVersion 29 buildToolsVersion "29.0.3" defaultConfig { applicationId "com.aimerneige.databindingdemo" minSdkVersion 24 targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" dataBinding { enabled true } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } 为布局文件提供 dataBinding 支持 在布局文件开头点击黄色灯泡(或按ALT + Enter),选择以下操作将布局文件转换为 data binding layout ,获取 data binding 支持 ...

二月 22, 2020 · Aimer Neige

使用 ProgressDialog 实现加载提示

在进行一些耗时操作的时候,经常需要加载提示框来提醒用户当前在进行耗时操作,需要等待。 而实现这样一个加载框十分简单。 构建 ProgressDialog 对象 你可以在耗时操作开始前临时建立新的 ProgressDialog 对象,你也同样可以在 Activity 中构建 ProgressDialog 的引用,并在 OnCreate 方法内构建实体,在需要的时候直接显示和隐藏。 其中前者相对灵活,但是使用范围有限,后者使用范围较广,但是可以会使得 OnCreate 中的代码较为繁琐。 但是,不管使用那种方法,ProgressDialog 的构建都是非常简单。 ProgressDialog progressDialog; progressDialog = new ProgressDialog(MainActivity.this); // ProgressDialog progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setTitle("This is Title"); progressDialog.setMessage("This is Message"); progressDialog.setCancelable(true); 其他属性可自行探索或者查阅官方文档 显示加载框 在耗时操作开始前(或者任何你想要显示提示框的地方),通过以下操作显示加载框: progressDialog.show(); 关闭提示框 在耗时操作关闭时(或者任何你想要关闭提示框的地方),通过以下操作关闭加载框: progressDialog.hide(); 很简单不是吗 又水了一期,不过好像没人看我的博客

二月 20, 2020 · Aimer Neige

使用 LiveData 优雅地管理布局显示的数据

ViewModel 提供了一个可以管理数据的优雅的容器,但是它也只是存储数据而已,并不能对数据进行处理,只是存储数据而已,但是如果使用 LiveData 来辅助, ViewModel 不再只是存储数据,它本身也能处理界面内容,就像它的名字一样,能让数据活起来。 在 ViewModel 中构建 LiveData 对象 与 ViewModel 不同, LiveData 不需要构建类,直接在 ViewModel 中创建对象即可。 首先创建 ViewModel 对象,然后在 ViewModel 对象中创建 LiveData 字段 package com.aimerneige.livedatatest; import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; public class ViewModelWithLiveData extends ViewModel { private MutableLiveData<Integer> LikedNumber; } 然后为 LiveData 对象构建 get 方法 // May Cause Error public MutableLiveData<Integer> getLikedNumber() { return LikedNumber; } 要注意的是构建的对象如果没有构建的话是为空的,直接返回会有空指针错误,所以要对空指针进行处理。 在构造方法中解决 // One possible wey to make the LikedNumber not null ViewModelWithLiveData () { LikedNumber = new MutableLiveData<>(); LikedNumber.setValue(0); } 在 get 方法中解决(推荐) public MutableLiveData<Integer> getLikedNumber() { if (LikedNumber == null) { LikedNumber = new MutableLiveData<>(); LikedNumber.setValue(0); } return LikedNumber; } 接下来为数据提供操作方法,要注意的是这里非常不建议直接提供 set 方法对数据进行修改。这里以增加(减少)数据大小为例: ...

二月 20, 2020 · Aimer Neige

使用 ViewModel 管理布局上的数据

如果不进行处理的话,布局上的临时数据可能会因为屏幕反转,切换系统语言等而消失,但是处理过程略微繁琐,较为麻烦,但是谷歌为我们提供了一种更加简洁的方式来管理界面数据,那就是 ViewModel。 构建自己的 ViewModel 类 新建 Java 类,继承至ViewModel,名字自定义,这里以MyViewModel为例。 package com.aimerneige.viewmoudeltest; import androidx.lifecycle.ViewModel; public class MyViewMoude extends ViewModel { } 新建好类之后,直接将需要用到的数据填写在内部,可以直接使用 public 的数据类型(不推荐),或者使用 private 数据加 get 方法。 package com.aimerneige.viewmoudletest; import androidx.lifecycle.ViewModel; public class MyViewMoude extends ViewModel { public int number = 0; public String test = "Test for 100"; private int age = 0; public int getAge() { return age; } public void setAge(int age) { this.age = age; } } 然后把ViewModel当成一个智能地存储数据的结构体使用即可。 在 Activity 中使用 ViewModel 在MainActivity内构建MyViewMoude的引用 MyViewMoude myViewMoude; 在 onCreate 方法内获得 MyViewMoude 的实体 ...

二月 20, 2020 · Aimer Neige

ToolBar

MaterialDesign 依赖库 implementation 'com.google.android.material:material:1.1.0' 在布局文件中加入 TooBar <androidx.appcompat.widget.Toolbar android:id="@+id/toolBar" android:layout_width="match_parent" android:layout_height="wrap_content" <!--其他属性设置--> /> 关于旧版的说明 旧版需要使用兼容包 compile 'com.android.support:appcompat-v7:23.1.1' 使用以下布局方法 <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="标题" android:textSize="20sp"/> </android.support.v7.widget.Toolbar> 很多文章都是这么写的,此处代码也是拷贝的,但是在开发中出了一些问题,博主是没有成功运行,仅供参考,挂了请自行查阅资料,不做解释。这里主要介绍新版 ToolBar 的使用 在 MainActivity 中引用 Toolbar Toolbar toolbar = findViewById(R.id.toolBar); 使用 ToolBar 作为界面布局 toolbar.setTitle("AppBarLayoutTest"); setSupportActionBar(toolbar); 导包的时候导这个,不要导错了,否则会报错 import androidx.appcompat.widget.Toolbar; 添加自定义属性 按需添加自定义属性,可以修改的内容包括标题的文字、图标、颜色等。不详细介绍,官方文档里很详细。 官方文档:https://developer.android.com/reference/android/widget/Toolbar 添加菜单 构建菜单的布局文件 这里添加的 item 会按顺序显示在 ToolBar 上面。 showAsAction 属性: always:总是显示 ifRoom:空间足够时显示 never:永不显示(收纳在右侧的三条横线那个更多按钮里) <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <item android:id="@+id/toolbar_setting" android:icon="@drawable/ic_setting" android:title="@string/toolbar_setting" app:showAsAction="always" /> <item android:id="@+id/toolbar_about" android:title="@string/toolbar_about" app:showAsAction="never" /> <item android:id="@+id/toolbar_exit" android:title="@string/toolbar_exit" app:showAsAction="never" /> </menu> 在主菜单中引用菜单的布局文件 @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.toolbar, menu); return true; } 设置菜单点击事件 @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case android.R.id.home: drawerLayout.openDrawer(GravityCompat.START); break; case R.id.toolbar_setting: Toast.makeText(MainActivity.this, "Waiting for coding for setting", Toast.LENGTH_SHORT).show(); break; case R.id.toolbar_about: Toast.makeText(MainActivity.this, "Waiting for coding for about", Toast.LENGTH_SHORT).show(); break; case R.id.toolbar_exit: Toast.makeText(MainActivity.this, "Waiting for coding for exit", Toast.LENGTH_SHORT).show(); break; default: break; } return true; } AppBarLayout 使用 AppBarLayout 可以给 ToolBar 定义更多的内容,并且 TabLayout 一般也是嵌套在其内部。 ...

二月 18, 2020 · Aimer Neige

使用 Gson 解析 Json 数据

新建项目 导入 Gson 依赖 implementation 'com.google.code.gson:gson:2.8.5' 设计布局 这里设计俩个 TextView 和一个 Button,点击 Button 后发送 Http 请求获取 Json 数据,并且通过 Gson 进行解析,将解析结果显示在 TextView 上,以此验证解析成功。 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/text1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="nodata"/> <TextView android:id="@+id/text2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="nodata"/> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test"/> </LinearLayout> 代码很简单就不多解释了。另外 在 Activity 中注册控件 的内容也省略。 发送 Http 请求并获取数据 操作同一般的 HTML 源码获取,这里不多解释。由于保存在网络上的 Json 数据其源码就是合法的 Json 字符串,因此通过解析网页源码的方法获取的内容就是 Json 数据。这里有一个网页保存了 Json 数据,可用于测试。 https://user.moecraft.net:8443/API/Mc/authlib/ 获取源码之后将其保存在一个字符串内即可继续进行下一步操作。此处命名为 jsonData。 ...

二月 17, 2020 · Aimer Neige

设置网络图片

通过网络连接获取图片信息,并将其设为软件的 ImageView 图片属性 介绍: 与获取 HTML 类似,首先需要建立网络连接并获取数据,只是这次不通过 String 获取保存数据,而是使用 Bitmap 保存。 与获取 HTML 数据类似,联网操作同样需要新建线程,要注意的是在子线程不能操作 UI,需要通过外部函数设置图片或者在函数返回 Bitmap 对象使用。 核心代码: 建立网络连接,这里使用 HttpURLConnection URL url = new URL("https://www.example.com.img") HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); // ...... // 诸如超时时间等的设置 处理返回数据 InputStream is = connection.getInputStream(); Bitmap bitmap = BitmapFactory.decodeStream(is); 设置控件,注意该操作不能在子线程中进行 imageView.setImageBitmap(bitmap); 完整代码 代码很烂,有很多可以优化的地方 //设置网络图片 public void setUrlImage(final int ImageViewId, final String address) { //开启一个线程用于联网 new Thread(new Runnable() { @Override public void run() { try { //把传过来的路径转成URL URL url = new URL(address); //获取连接 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); //使用GET方法访问网络 connection.setRequestMethod("GET"); //超时时间为10秒 connection.setConnectTimeout(10000); //获取返回码 int code = connection.getResponseCode(); if (code == 200) { InputStream inputStream = connection.getInputStream(); //使用工厂把网络的输入流生产Bitmap Bitmap bitmap = BitmapFactory.decodeStream(inputStream); //子线程不能操作UI,通过外部函数设置图片 setImage(ImageViewId, bitmap); inputStream.close(); } else { //服务启发生错误,显示提示信息 Toast.makeText(HttpImage.this, "Can't get the image from Internet.", Toast.LENGTH_SHORT).show(); } } catch (Exception e) { e.printStackTrace(); } } }).start(); } public void setImage(int ImageViewId, Bitmap bitmap) { ImageView imageView = findViewById(ImageViewId); imageView.setImageBitmap(bitmap); } 一些废话 实际上和处理 HTML 是类似的,只不过不再使用 String 处理服务器返回的数据。 ...

二月 16, 2020 · Aimer Neige

使用 GsonFormat 插件快速构建 Json 映射对象

插件安装 File Settings Plugins Marketplace 在搜索框输入 GsonFormat 搜索 安装相应插件 根据提示重启 IDE 使用方法 新建实体类 ALT + Insert 或者 右键->Generate 选择 GsonFormat 将待解析 Json 字符串输入弹出的对话框 OK

二月 16, 2020 · Aimer Neige

Swiperefreshlayout

GoogleDoc GoogleGithub 声明依赖项 直接复制官方文档,不多解释了(懒 在应用或模块的 build.gradle 文件中添加所需工件的依赖项: dependencies { implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" } 如需详细了解依赖项,请参阅添加编译依赖项。 添加布局 在 xml 布局文件中添加 SwipeRefreshLayout,并将 WebView 内嵌在 SwipeRefreshLayout 中。 布局这里拷贝了别人的代码,结果软件闪退,搞了半天找不到原因,重开了一个项目,根据代码提示写了一份居然可以运行,分明代码一样的,好迷啊。。。。。 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/swipe_refresh" android:layout_width="match_parent" android:layout_height="match_parent"> <WebView android:id="@+id/web_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </LinearLayout> SwipeRefreshLayout 类似 ScrollView,内部只能有一个部件,但是你可以这样玩、(手动滑稽 <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="test_scroll" android:textSize="16sp" /> </LinearLayout> </ScrollView> 编写代码部分 先放一个完整的源码,看不懂直接跳过,下面介绍关于 Swiperefreshlayout 的核心代码 ...

二月 1, 2020 · Aimer Neige