栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Java

【Android】Kotlin学习小结

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Android】Kotlin学习小结

目录
  • Android——Kotlin学习
    • 1. 使用控件id直接使用控件
    • 2. 继承类实现接口
    • 3. 点击事件监听
    • 4. 点击事件接口实现
    • 5. 页面跳转
    • 6. 文本操作
    • 7. 网络请求数据
    • 8. Kotlin的变量、常量
    • 9. 你真的理解全局变量吗?
    • 10. 闭包概念
    • 11. Fragment使用
    • 12. RecyclerView使用
    • 13. RecyclerView点击事件
    • 14. 数据传递(通过Intent)
    • 15. 数据回传
    • 16. 线程同步
    • 17. 数据存储——五大存储
    • 18. 四大组件
    • 19. 六大布局
    • 20. Glide框架的使用
    • 21. 圆形图片

不积跬步,无以至千里;不积小流,无以成江海。要沉下心来,诗和远方的路费真的很贵!

Android——Kotlin学习 1. 使用控件id直接使用控件
  • 在build.gradle文件中的plugins代码块中加入以下语句。
id 'kotlin-android-extensions'
  • 在逻辑文件中,声明其布局文件。
import kotlinx.android.synthetic.main.activity_main.*
  • 在后续使用Fragment进行学习时,遇到了直接使用控件id来使用控件的问题。其总是报空指针,加入?.后,虽然不会出现崩溃的情况,但是却也不能显示出控件,证明其确实未加载。
  • 百思不得其解,通过学习后发现:在Kotlin中直接使用id操作控件的情况,必须在布局文件加载完毕后使用才可以,因为只有加载完毕了,其才存在;布局文件都没加载,如何来的id,怎么去使用,肯定是报空的。所以在Fragment中,我们习惯性在onCreateView方法中使用id来操作控件肯定是会报空的,因为view都还没有return。
2. 继承类实现接口
  • 冒号后继承和实现,带有()的属于类,是继承;没有()的属于接口,是实现。
class MainActivity : AppCompatActivity(), View.OnClickListener{...}
3. 点击事件监听
  • 和Java语法一致。
fun initClick() {
        //跳转页面功能
        btn_register.setOnClickListener(this)
        //网络请求功能
        btn_login.setOnClickListener(this)
        //文本控件操作功能
        btn_reset.setOnClickListener(this)
    }
4. 点击事件接口实现
  • 不再是使用switch了,而是使用when。
override fun onClick(v: View?) {
        when (v?.id) {
            //点击注册,跳转进入注册页面
            R.id.btn_register -> {
                //创建跳转对象
                val intent = Intent(this, MainActivity2::class.java)
                //进行页面跳转
                startActivity(intent)
            }
            //点击监听,得到网络请求数据
            R.id.btn_login -> {
                val intent = Intent(this, HomeActivity::class.java)
                //进行页面跳转
                startActivity(intent)
                getDataByInternet()
            }
            R.id.btn_reset -> {
                edit_username.setText("")
                edit_password.setText("")
            }
        }
    }
5. 页面跳转
  • 依然是用Intent进行界面跳转。
val intent = Intent(this, HomeActivity::class.java)
                //进行页面跳转
                startActivity(intent)
6. 文本操作
  • get类方法,直接属性调用,都不需要get了;set类方法可有两种操作。
Log.i("testData", edit_username.text.toString())
                Log.i("testData", edit_password.text.toString())
                //setText  Java版本
                edit_username.setText("")
                edit_password.setText("")
                // = 版本
                edit_username.text = ""
                edit_password.text = ""
7. 网络请求数据
  • 使用Retrofit进行网络数据的请求。
  1. 创建数据对象。
class User(
    val id : Int,
    val username : String,
    val password : String,
    val nickname : String,
    val avatar : String,
    val sex : String,
    val age : Int,
    val phone : String,
    val email : String,
    val islogin : String
)
  1. 创建代理接口。

interface ApiService {

    @GET("user")
    fun listUser(): Call>

    @GET("recipe")
    fun listRecipe() : Call>
}
  1. 创建网络连接。
private lateinit var retrofit: Retrofit
    private lateinit var api: ApiService



    fun initSocket() {
        // builder模式构建Retrofit对象
        retrofit = retrofit2.Retrofit.Builder()
            .baseUrl("https://www.fastmock.site/mock/d6931ad23f0e1bdb2061d1c5363c45cb/KotlinLearning/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
        // 创建接口层的代理对象,内部通过动态代理创建了ApiService的代理对象
        api = retrofit.create(ApiService::class.java)
    }
  1. 进行网络请求。
    fun getDataByInternet() {
        // 执行异步请求
        api.listUser().enqueue(object : Callback> {
            override fun onResponse(call: Call>, response: Response>) {
                Log.e("data", response.body().toString())
                response.body()?.let { it1 -> Log.e("data", it1.size.toString()) }
                for (i in 0 until (response.body()?.size!!)) {
                    response.body()?.get(i)?.let { it1 -> Log.e("onResponse", it1.id.toString()) }
                    response.body()?.get(i)?.let { it1 -> Log.e("onResponse", it1.username) }
                    response.body()?.get(i)?.let { it1 -> Log.e("onResponse", it1.password) }
                    response.body()?.get(i)?.let { it1 -> Log.e("onResponse", it1.nickname) }
                    response.body()?.get(i)?.let { it1 -> Log.e("onResponse", it1.avatar) }
                    response.body()?.get(i)?.let { it1 -> Log.e("onResponse", it1.sex) }
                    response.body()?.get(i)?.let { it1 -> Log.e("onResponse", it1.age.toString()) }
                    response.body()?.get(i)?.let { it1 -> Log.e("onResponse", it1.phone) }
                    response.body()?.get(i)?.let { it1 -> Log.e("onResponse", it1.email) }
                    response.body()?.get(i)?.let { it1 -> Log.e("onResponse", it1.islogin) }
                }
            }

            override fun onFailure(call: Call>, t: Throwable) {
                Log.e("onFailure", t.toString())
            }
        })
    }
8. Kotlin的变量、常量
  • 以Fragment为例子,进行常量变量总结。
  1. 变量(延迟加载)——lateinit var
  • 变量可以读写,可以修改赋值。
private lateinit var homeFragment: HomeFragment

变量延迟加载,是声明变量时不加载,使用其时才加载,即懒汉式加载。无论其有无声明,在没有创建前使用它,会报错。

if(homeFragment == null){
            homeFragment = HomeFragment()
        }

上述代码中,未创建homeFragment,就使用其来判断是否为空,故会报错。

  • 正确变量写法。
private var myFragment : MyFragment? = null

?代表该对象可为空。

  • 为空时执行。
myFragment?:let {
            myFragment = MyFragment()
            fragmentTransaction.add(R.id.fragment,myFragment!!)
        }
  • 不为空时执行。
myFragment?.let { fragmentTransaction.show(it) }
  1. 常量——val
  • 就是一个只可读变量,只可以初始化一次。
private val homeFragment : HomeFragment = HomeFragment()
private val homeFragment3 : HomeFragment

init {
        homeFragment3 = HomeFragment()
    }

常量要么在声明时直接初始化,要么在构造函数init中初始化。

9. 你真的理解全局变量吗?
  • C语言提供了全局变量的定义,其又称:外部变量。
  • 顾名思义,定义在函数外的变量,称为外部变量。
  • 它的作用域是整个源程序,所以可以在整个源程序的任意位置访问全局变量。
  • 其不仅仅是在一个类中,叫全局变量;而是在整个源程序中。
  • 全局变量位于整个源程序中,所以它们同生共死,只要程序没有停止,它就不会消失。
10. 闭包概念
  • 闭包是一个能够访问其他函数内部变量的函数。
11. Fragment使用
  • 例子——在Activity中结合Fragment显示界面。
  • 逻辑都存在于Activity中,因为Fragment的跳转等都是在Activity中执行的。
  1. 声明需要显示的Fragment。
private var homeFragment : HomeFragment? = null
    private var recipeFragment : RecipeFragment? = null
    private var discussionFragment : DiscussionFragment? = null
    private var myFragment : MyFragment? = null
  1. 创建底部栏监听。
 
    private fun initClick() {
        ll_home.setOnClickListener(this)
        ll_recipe.setOnClickListener(this)
        ll_discussion.setOnClickListener(this)
        ll_person.setOnClickListener(this)
    }
  1. 初始化时,底部栏变化,显示第一个Fragment。
//创建的时候显示首页
        ll_home?.isSelected = true
        ll_recipe?.isSelected = false
        ll_discussion?.isSelected = false
        ll_person?.isSelected = false
        initHomeFragment()
  1. 显示Fragment。
  • 注意:每一个Fragment显示都需要一个新的事务,因为事务提交了,就失效了,需要一个新的。
private fun initHomeFragment() {
        //每一个Fragment都需要一个单独的事务
        //因为提交后,事务虽然创建方式一样,但是本质已经不同
        var fragmentTransaction : FragmentTransaction = supportFragmentManager.beginTransaction()
        //若是homeFragment为空
        homeFragment?:let {
            homeFragment = HomeFragment()
            fragmentTransaction.add(R.id.fragment, homeFragment!!)
        }
        //隐藏事务中所有的Fragment
        hideAllFragment(fragmentTransaction)
        //显示需要显示的Fragment
        homeFragment?.let { fragmentTransaction.show(it) }
        //提交事务,事务一定要提交,不然无效
        fragmentTransaction.commit()
    }
  1. 隐藏所有的Fragment。
    private fun hideAllFragment(fragmentTransaction: FragmentTransaction) {
        homeFragment?.let { fragmentTransaction.hide(homeFragment!!) }
        recipeFragment?.let { fragmentTransaction.hide(recipeFragment!!) }
        discussionFragment?.let { fragmentTransaction.hide(discussionFragment!!) }
        myFragment?.let { fragmentTransaction.hide(myFragment!!) }
    }
  1. 点击底部栏,显示不同的Fragment。
override fun onClick(v: View?) {
        when (v?.id) {
            R.id.ll_home -> {
                ll_home?.isSelected = true
                ll_recipe?.isSelected = false
                ll_discussion?.isSelected = false
                ll_person?.isSelected = false
                initHomeFragment()
            }
            R.id.ll_recipe -> {
                ll_home?.isSelected = false
                ll_recipe?.isSelected = true
                ll_discussion?.isSelected = false
                ll_person?.isSelected = false
                initRecipeFragment()
            }
            R.id.ll_discussion -> {
                ll_home?.isSelected = false
                ll_recipe?.isSelected = false
                ll_discussion?.isSelected = true
                ll_person?.isSelected = false
                initDiscussionFragment()
            }
            R.id.ll_person -> {
                ll_home?.isSelected = false
                ll_recipe?.isSelected = false
                ll_discussion?.isSelected = false
                ll_person?.isSelected = true
                initMyFragment()
            }
            else -> { }
        }
    }
12. RecyclerView使用
  • 例子——利用RecyclerView实现方剂数据的展示。
  • 效果图如下:

  1. 准备数据类。
package com.example.myapplication.model


class Recipe(
    val id: Int,
    val name: String,
    val song: String,
    val medicines: String,
    val function: String,
    val cure: String,
    val type: String,
    val childtype: String,
    val book: String
)
  1. 准备后端接口。
@GET("recipe")
    fun listRecipe() : Call>
  1. 准备布局和item布局。
  • 布局只有一个RecyclerView,子布局如下:



    

    

    


  1. 创建item适配器。
package com.example.myapplication.adapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.myapplication.R
import com.example.myapplication.model.Recipe


class RecipeAdapter(private val recipeList : List) : RecyclerView.Adapter(){
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecipeAdapter.MyViewHolder {
        //加载子布局
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_recipe,parent,false)
        return MyViewHolder(view)
    }

    override fun onBindViewHolder(holder: RecipeAdapter.MyViewHolder, position: Int) {
        //操作控件
        val item = recipeList[position]
        with(holder){
            tv_recipe_name.text = item.name
            tv_recipe_function.text = item.function
            tv_recipe_book.text = item.book
        }
    }

    override fun getItemCount(): Int {
        //返回数据数目
        return recipeList.size
    }

    inner class MyViewHolder(view : View) : RecyclerView.ViewHolder(view){
        //获取控件
        val tv_recipe_name : TextView = view.findViewById(R.id.tv_recipe_name)
        val tv_recipe_function : TextView = view.findViewById(R.id.tv_recipe_function)
        val tv_recipe_book : TextView = view.findViewById(R.id.tv_recipe_book)
    }
}
  1. 使用适配器和RecyclerView控件。
package com.example.myapplication.fragment

import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.myapplication.R
import com.example.myapplication.adapter.RecipeAdapter
import com.example.myapplication.model.Recipe
import com.example.myapplication.tools.ApiService
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory


class RecipeFragment : Fragment() {
    //控件
    private lateinit var rcv_recipe: RecyclerView
    //网络连接
    private lateinit var retrofit: Retrofit
    //网络接口
    private lateinit var api: ApiService
    //适配器
    private var recipeAdapter: RecipeAdapter? = null
    //数据列表
    private var recipeList = ArrayList()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        //加载布局
        val view = LayoutInflater.from(container?.context)
            .inflate(R.layout.fragment_recipe, container, false)
        //获取控件RecyclerView
        rcv_recipe = view.findViewById(R.id.rcv_recipe)
        
        initSocket()
        initData()

        return view
    }

    
    private fun initSocket() {
        // builder模式构建Retrofit对象
        retrofit = retrofit2.Retrofit.Builder()
            .baseUrl("https://www.fastmock.site/mock/d6931ad23f0e1bdb2061d1c5363c45cb/KotlinLearning/")
            .addConverterFactory(GsonConverterFactory.create())
            .build()
        // 创建接口层的代理对象,内部通过动态代理创建了ApiService的代理对象
        api = retrofit.create(ApiService::class.java)
    }

    
    private fun initData() {
        //异步加载网络数据
        api.listRecipe().enqueue(object : Callback> {
            override fun onResponse(call: Call>, response: Response>) {
                //打印数据数量
                response.body()?.let { it1 -> Log.e("size", it1.size.toString()) }
                for (i in 0 until (response.body()?.size!!)) {
                    //循环加入数据列表
                    response.body()?.get(i)?.let { it1 ->
                        recipeList.add(it1)
                    }
                }
                //设置垂直布局
                val linearLayoutManager = LinearLayoutManager(activity)
                linearLayoutManager.orientation = LinearLayoutManager.VERTICAL
                rcv_recipe.layoutManager = linearLayoutManager
                //添加下划线
                rcv_recipe.addItemDecoration(DividerItemDecoration(activity, LinearLayoutManager.VERTICAL))
                //加载适配器
                recipeAdapter = RecipeAdapter(recipeList)
                rcv_recipe.adapter = recipeAdapter
            }

            override fun onFailure(call: Call>, t: Throwable) {
                Log.e("onFailure", t.toString())
            }
        })
    }
}

注意:适配器加载不放在onCreateView中,是因为异步请求,可能网络请求的线程还没有执行完毕,就进行了适配器加载,导致出现没有数据的情况,需要进行线程同步。但是放在网络请求线程中,可以保证其在同一个线程,必然在数据请求完毕后,再进行适配器的加载,必然有数据。若是就不要放在同一个线程中,那么就进行线程的同步,这个在下文序号16进行阐述。

13. RecyclerView点击事件
  • RecyclerView的点击事件就是item的点击响应。
  • 所以将item的子布局设置一个点击监听即可。
layout_recipe.setOnClickListener(View.OnClickListener {
                val intent = Intent(context,RecipeActivity::class.java)
                context.startActivity(intent)
            })
  • layout_recipe是item子布局的id,对其设置点击事件,内部代码为点击其所执行的具体操作。
14. 数据传递(通过Intent)
  1. Activity传递到Activity。
  • 例子——登录界面(MainActivity.kt)跳转到主页面(HomeActivity.kt),传递过去登录用户信息并打印在日志栏中。

  • MainActivity.kt

//声明Bundle传递对象
private var bundle : Bundle ?= null

//创建传递对象
                bundle = Bundle()
                //加入第一个用户数据
                response.body()?.get(0)?.id?.let { bundle?.putInt("id", it) }
                response.body()?.get(0)?.username?.let { bundle?.putString("username", it) }
                response.body()?.get(0)?.password?.let { bundle?.putString("password", it) }
                response.body()?.get(0)?.nickname?.let { bundle?.putString("nickname", it) }
                response.body()?.get(0)?.avatar?.let { bundle?.putString("avatar", it) }
                response.body()?.get(0)?.sex?.let { bundle?.putString("sex", it) }
                response.body()?.get(0)?.age?.let { bundle?.putInt("age", it) }
                response.body()?.get(0)?.phone?.let { bundle?.putString("phone", it) }
                response.body()?.get(0)?.email?.let { bundle?.putString("email", it) }
                response.body()?.get(0)?.islogin?.let { bundle?.putString("islogin", it) }
                //创建跳转对象
                intent = Intent(this@MainActivity, HomeActivity::class.java)
                //传递对象不为空,跳转对象不为空,就存入
                bundle?.let { intent?.putExtras(it) }
                //进行页面跳转
                startActivity(intent)
  • 此处在网络请求数据线程中进行跳转,原因还是因为线程同步的问题。要是不在此处跳转,无法确保bundle对象中一定存在数据。而且由于不在主线程进行跳转,所以要使用@MainActivity告知Intent对象跳转的起点位于MainActivity。
  • HomeActivity.kt
//获取传递过来的数据存储对象
        //自动判断类型,无需手动书写
        var bundle = this.intent.extras
        var sb = StringBuilder()
        sb.append(bundle?.getInt("id"))
        sb.append(bundle?.getString("username"))
        sb.append(bundle?.getString("password"))
        sb.append(bundle?.getString("nickname"))
        sb.append(bundle?.getString("avatar"))
        sb.append(bundle?.getString("sex"))
        sb.append(bundle?.getInt("age"))
        sb.append(bundle?.getString("phone"))
        sb.append(bundle?.getString("email"))
        sb.append(bundle?.getString("islogin"))
        Log.e("bundle",sb.toString())
  • Kotlin语言中,String无法使用+号进行连接,因此此处使用StringBuilder来连接字符串。:要是需要线程安全的,可以使用StringBuffer来连接字符串。
  1. Activity 传递到Fragment。
  • 例子——主页面(HomeActivity.kt)传递登录用户信息到个人主页(即最后一个Fragment,即MyFragment.kt),然后在个人主页面进行用户信息显示。

  • MainActivity.kt

//声明Bundle传递对象
private var bundle : Bundle ?= null

//获取传递过来的数据存储对象
        //自动判断类型,无需手动书写
        bundle = this.intent.extras
        
private fun initMyFragment() {
        var fragmentTransaction : FragmentTransaction = supportFragmentManager.beginTransaction()
        myFragment?:let {
            myFragment = MyFragment()
            //将数据传递给fragment
            myFragment?.arguments = bundle
            fragmentTransaction.add(R.id.fragment,myFragment!!)
        }
        //隐藏事务中所有的Fragment
        hideAllFragment(fragmentTransaction)
        //显示需要显示的Fragment
        myFragment?.let { fragmentTransaction.show(it) }
        //提交事务,事务一定要提交,不然无效
        fragmentTransaction.commit()
    }
  • bundle是用户从登录页面Activity传递过来的,主页面Activity接收一下,直接就传递给了Fragment,没有经过其他处理。(PS:哪个Fragment需要数据,就在哪个Fragment的arguments中赋值即可)

  • 传递过来的具体数据格式即为第1小点中传递过来的数据格式。

  • MyFragment.kt

package com.example.myapplication.fragment

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.myapplication.R
import kotlinx.android.synthetic.main.fragment_my.*
import java.lang.StringBuilder

class MyFragment : Fragment() {
    //声明Bundle存储对象
    private var bundle : Bundle ?= null
    private var sb : StringBuilder ?= null

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        //获取数据存储对象
        bundle = this.arguments
        //连接字符串
        sb = StringBuilder()
        sb?.append(bundle?.getInt("id"))
        sb?.append(",")
        sb?.append(bundle?.getString("username"))
        sb?.append(",")
        sb?.append(bundle?.getString("password"))
        sb?.append(",")
        sb?.append(bundle?.getString("nickname"))
        sb?.append(",")
        sb?.append(bundle?.getString("avatar"))
        sb?.append(",")
        sb?.append(bundle?.getString("sex"))
        sb?.append(",")
        sb?.append(bundle?.getInt("age"))
        sb?.append(",")
        sb?.append(bundle?.getString("phone"))
        sb?.append(",")
        sb?.append(bundle?.getString("email"))
        sb?.append(",")
        sb?.append(bundle?.getString("islogin"))

        return inflater.inflate(R.layout.fragment_my, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        //传递过来的数据显示在界面上
        tv_test.text = sb.toString()
    }
}
  • 此处在Fragment中调用id直接操作控件,需要在View返回之后,所以在onViewCreated方法中使用,因为onViewCreated方法在onCreateView方法之后执行。
  • 还有一种方式,就是先加载Fragment的布局文件,然后通过findViewById得到控件。
  • 效果图如下:

  1. 上述序号13的传递是item点击到一个activity界面,所以数据是从Fragment传递到Activity。
  • 以上例点击事件为例子,点击item,跳转到另一个界面,并传递过去方剂数据。

  • RecipeAdapter.kt

//页面跳转逻辑
                var intent = Intent(context,RecipeActivity::class.java)
                //数据存储对象
                var bundle = Bundle()
                //将数据保存进去
                bundle.putInt("id",item.id)
                bundle.putString("name",item.name)
                bundle.putString("song",item.song)
                bundle.putString("medicines",item.medicines)
                bundle.putString("function",item.function)
                bundle.putString("cure",item.cure)
                bundle.putString("type",item.type)
                bundle.putString("childtype",item.childtype)
                bundle.putString("book",item.book)
                //将数据对象保存进跳转对象
                intent.putExtras(bundle)
                //实现跳转传递
                context.startActivity(intent)
  • RecipeActivity.kt
//获取传递过来的数据对象
        var bundle = this.intent.extras
        //将数据放入文本控件显示
        tv_id.text =  bundle?.getInt("id").toString()
        tv_name.text = bundle?.getString("name")
        tv_song.text = bundle?.getString("song")
        tv_medicines.text = bundle?.getString("medicines")
        tv_function.text = bundle?.getString("function")
        tv_cure.text = bundle?.getString("cure")
        tv_type.text = bundle?.getString("type")
        tv_childtype.text = bundle?.getString("childtype")
        tv_book.text = bundle?.getString("book")
  • 效果图如下:

  1. Fragment传递到Fragment。
  • 位于同一个Activity的Fragment的数据,可以通过Activity进行传递;位于不同Activity的Fragment,可以通过Fragment本身和Activity作为中间媒介进行传递。
  • 总结来说,这一种传递过程,就是前三种过程的结合实现。
15. 数据回传
  • 数据回传必定是传递回去修改后的数据,若是没有修改,回传就没有意义。
16. 线程同步
  • 线程同步的含义:无论多少个线程执行,确保最后的结果是可确定的,即无论怎么执行,最后的结果是不变的。
17. 数据存储——五大存储
  1. SharedPreferences
  2. 文件存储
  3. SQLite数据库
  4. 四大组件之内容提供器(Content Provider)
  5. 网络存储
18. 四大组件
  1. Activity
  2. Service
  3. Broadcast Receiver
  4. Content Provider
19. 六大布局
  1. 线性布局(LinearLayout)
  2. 表格布局(TableLayout)
  3. 帧布局(FrameLayout)
  4. 相对布局(RelativeLayout)
  5. 网格布局(GridLayout)
  6. 绝对布局(AbsoluteLayout)
20. Glide框架的使用
  1. 导入依赖。
implementation 'com.github.bumptech.glide:glide:4.11.0'  //Glide
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
  1. 加入网络请求权限。

  1. 使用其进行图片加载。
//加载控件
        Glide.with(img_avatar)
            //形成bitmap类型
            .asBitmap()
            //加载图片网址
            .load(bundle?.getString("avatar"))
            //预加载
            .placeholder(R.mipmap.person_selected)
            //加载错误显示图片
            .error(R.drawable.btn_background)
            //放入控件
            .into(img_avatar)
activity?.let {
            Glide.with(it)
                //形成bitmap类型
                .asBitmap()
                //加载图片网址
                .load(bundle?.getString("avatar"))
                //预加载
                .placeholder(R.mipmap.person_selected)
                //加载错误显示图片
                .error(R.drawable.btn_background)
                //放入控件
                .into(img_avatar)
        }
  • 效果图如下:

21. 圆形图片
  • 利用圆形图片开源库(CircleImageView)。
  1. 导入依赖。
implementation 'de.hdodenhof:circleimageview:3.1.0'
  1. 在布局文件中,将ImageView控件改为de.hdodenhof.circleimageview.CircleImageView控件即可。
  • 效果图如下:

转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1039337.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号