【Android】全局加载框的使用

news2025/1/16 9:14:52

项目需求

在网络加载中使用网络加载框,在请求数据或者其他耗时操作的时候,显示加载框,当数据返回之后或者操作完成的时候加载框取消。
效果如下:
请添加图片描述

需求实现

使用一个开源库【Gloading】实现
项目地址链接: Gloading

1.引入依赖

//网络加载状态
api 'com.billy.android:gloading:1.1.0'

2.初始化(一般在Application里面初始化,在Activity也行)

//初始化Gloading  GlobalAdapter类需要我们自己创建
 Gloading.initDefault(new GlobalAdapter());

3.我们如果创建的是一个全局加载的加载框,那就创建一个基类Activity,命名为BaseActivity。

public class BaseActivity extends AppCompatActivity {
    protected Gloading.Holder mHolder;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    protected void initGloadingState() {
        if (mHolder == null) {
            mHolder = Gloading.getDefault().wrap(this).withRetry(new Runnable() {
                @Override
                public void run() {
                    onLoadRetry();
                }
            });
        }
    }
     //加载失败重试时使用
    protected void onLoadRetry() {}

    //这是可以显示特定文字的加载框,如此方法就可显示【请求登录】
    public void showLogin() {
        initGloadingState();
        mHolder.withData("请求登录");
        mHolder.showLoading();
    }

    public void showLoginSuccess() {
        initGloadingState();
        mHolder.withData("登录成功");
        mHolder.showLoadSuccess();
    }

    public void showLoginFailed() {
        initGloadingState();
        mHolder.withData("登录失败\n点击重试");
        mHolder.showLoadFailed();
    }

    //这是显示默认文字的加载框
    public void showLoadingView() {
        initGloadingState();
        mHolder.showLoading();
    }

    public void showLoadingSuccessView() {
        initGloadingState();
        mHolder.showLoadSuccess();
    }

    public void showLoadingFailView() {
        initGloadingState();
        mHolder.showLoadFailed();
    }

}

4.基类Fragment,命名为BaseFragment,和Activity里面的差不多。

open class BaseFragment : Fragment() {

    private var mHolder: Gloading.Holder? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        initGloadingState()
        return super.onCreateView(inflater, container, savedInstanceState)
    }


    protected open fun initGloadingState() {
        if (mHolder == null) {
            mHolder = Gloading.getDefault().wrap(requireActivity()).withRetry { onLoadRetry() }
        }
    }

    protected open fun onLoadRetry() {}

    open fun showLoadingView() {
        initGloadingState()
        mHolder?.showLoading()
    }

    open fun showLoadingSuccessView() {
        initGloadingState()
        mHolder?.showLoadSuccess()
    }

    open fun showLoadingFailView() {
        initGloadingState()
        mHolder?.showLoadFailed()
    }

}

5.创建GlobalAdapter,这是我们初始化时需要的类

public class GlobalAdapter implements Gloading.Adapter {

    @Override
    public View getView(Gloading.Holder holder, View convertView, int status) {
        GlobalLoadingStatusView loadingStatusView = null;
        if (convertView instanceof GlobalLoadingStatusView) {
            loadingStatusView = (GlobalLoadingStatusView) convertView;
        }
        if (loadingStatusView == null) {
            loadingStatusView = new GlobalLoadingStatusView(holder.getContext(), holder.getRetryTask());
        }
        //这里获取传入的文字
        String strMessage = holder.getData();
        if (strMessage != null) {
            loadingStatusView.setStatus(status, strMessage);
        } else {
            loadingStatusView.setStatus(status, "");
        }
        holder.withData("");
        loadingStatusView.setMsgViewVisibility(true);
        return loadingStatusView;
    }

}

6.创建GlobalLoadingStatusView 类,GlobalAdapter需要此类

@SuppressLint("ViewConstructor")
public class GlobalLoadingStatusView extends RelativeLayout implements View.OnClickListener {

    private final TextView mTextView;
    private final Runnable mRetryTask;
    private final ImageView mImageView;

    public GlobalLoadingStatusView(Context context, Runnable retryTask) {
        super(context);
        setGravity(Gravity.CENTER_HORIZONTAL);
        LayoutInflater.from(context).inflate(R.layout.view_global_loading_status, this, true);
        RelativeLayout relativeLayout = findViewById(R.id.rv_gloading);
        relativeLayout.getBackground().mutate().setAlpha(150);
        mImageView = findViewById(R.id.image);
        mTextView = findViewById(R.id.text);
        this.mRetryTask = retryTask;
    }

    public void setMsgViewVisibility(boolean visible) {
        mTextView.setVisibility(visible ? VISIBLE : GONE);
    }

    //这里设置文字显示,如果不传入文字就使用下面的默认文字
    public void setStatus(int status, String message) {
        boolean show = true;
        View.OnClickListener onClickListener = null;
        int image = R.drawable.loading;
        String str = "";
        if (status == STATUS_LOAD_SUCCESS) {
            show = false;
        } else if (status == STATUS_LOADING) {
            str = "加载中...";
        } else if (status == STATUS_LOAD_FAILED) {
            str = "加载失败";
            image = R.drawable.icon_failed;
            Boolean networkConn = isNetworkConnected(getContext());
            if (networkConn != null && !networkConn) {
                str = "网络连接失败";
                image = R.drawable.icon_no_wifi;
            }
            onClickListener = this;
        } else if (status == STATUS_EMPTY_DATA) {
            str = "数据为空";
            image = R.drawable.icon_empty;
        }
        mImageView.setImageResource(image);
        setOnClickListener(onClickListener);
        if (message != null && !message.isEmpty()) {
            mTextView.setText(message);
        } else {
            mTextView.setText(str);
        }
        setVisibility(show ? View.VISIBLE : View.GONE);
    }

    @Override
    public void onClick(View v) {
        if (mRetryTask != null) {
            mRetryTask.run();
        }
    }
}

7.加载框视图【view_global_loading_status】

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:id="@+id/rv_gloading"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#333333"
    tools:ignore="UseCompoundDrawables">

    <androidx.cardview.widget.CardView
        android:layout_width="150dp"
        android:layout_height="200dp"
        android:layout_centerInParent="true"
        app:cardCornerRadius="10dp">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#99666666"
            android:orientation="vertical">

            <ImageView
                android:id="@+id/image"
                android:layout_width="80dp"
                android:layout_height="80dp"
                android:layout_gravity="center"
                android:layout_marginTop="40dp"
                tools:ignore="ContentDescription" />

            <TextView
                android:id="@+id/text"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="15dp"
                android:gravity="center"
                android:textColor="#FFFFFF"
                android:textSize="18sp" />
        </LinearLayout>
    </androidx.cardview.widget.CardView>
</RelativeLayout>

8.用到的图片
无网络【icon_no_wifi】
在这里插入图片描述
加载【icon_loading】
在这里插入图片描述
加载失败【icon_failed】
在这里插入图片描述
无数据【icon_empty】
在这里插入图片描述
我们在加载数据的时候,需要这个加载的图片动起来,创建xml文件,命名为【loading】

<?xml version="1.0" encoding="utf-8"?>
<animated-rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/icon_loading"
    android:fromDegrees="0.0"
    android:pivotX="50.0%"
    android:pivotY="50.0%"
    android:toDegrees="360.0" />

9.使用
创建一个Activity继承BaseActivity
在加载框使用中,当数据请求成功之后,加载框会消失,但是当数据请求失败的时候,加载框不会消失,就会卡在那里,但是我们有时候需要重试功能,所以在加载框失败的时候也不能简单的消失就行了,同时此时手机的返回键点击的时候会将整个Activity干掉,此时需要处理这个问题。

class LoginActivity : BaseActivity() {

    private lateinit var binding: ActivityLoginBinding
    private val loginViewModel: LoginModel by lazy {
        ViewModelProvider(this)[LoginModel::class.java]
    }
    private var nameStr = ""
    private var pwdStr = ""
    //判断请求状态
    private var isRequestLogin = false

    @SuppressLint("ClickableViewAccessibility")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityLoginBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.tvLogin.setOnClickListener {
            nameStr = binding.etLoginName.text.trim().toString()
            pwdStr = binding.etLoginPwd.text.trim().toString()
            if (nameStr.isEmpty() || pwdStr.isEmpty()) {
                Toast.makeText(this, "请输入账号或密码", Toast.LENGTH_SHORT).show()
            } else {
                requestLogin(nameStr, pwdStr)
            }
        }
    }

    //请求登录
    private fun requestLogin(username: String, password: String) {
        lifecycleScope.launch {
            loginViewModel.requestLogin(
                this@LoginActivity,
                username,
                password,
                object : IResult<LoginBean.LoginContent> {
                    override fun startView() {
                        //开始进行请求,此时请求状态为true
                        isRequestLogin = true
                        //展示显示请求登录的加载中的加载框
                        showLogin()
                    }

                    override fun successView(content: LoginBean.LoginContent?) {
                        //登录成功之后,调用登录成功加载框方法
                        showLoginSuccess()
                        //请求状态变为false
                        isRequestLogin = false

                    }

                    override fun failedView(failStr: String) {
                        if (isRequestLogin) {
                            //登录失败的时候,如果此时处于请求转态的话,展示失败加载框
                            showLoginFailed()
                            Log.e(TAG, "登录失败: $failStr")
                        }
                    }

                    override fun errorView(exception: Throwable) {
                        if (isRequestLogin) {
                            //登录错误的时候,如果此时处于请求转态的话,展示失败加载框
                            showLoginFailed()
                            Log.e(TAG, "登录错误: $exception")
                        }
                    }
                })
        }
    }
   //重试,在加载失败或者错误时,点击屏幕可以重新加载操作
    override fun onLoadRetry() {
        super.onLoadRetry()
        requestLogin(nameStr, pwdStr)
    }
    //监听返回键
    override fun onBackPressed() {
        if (isRequestLogin) {
            //当处于请求加载状态的时候,点击返回按钮,显示加载成功(加载成功的界面其实不会显示,因为
            //根本没有这个页面,同时看上面GlobalLoadingStatusView 类的代码就可以知道,
            //当成功的时候,视图的visibility==Gone)
            showLoginSuccess()
            isRequestLogin = false
        } else {
            super.onBackPressed()
        }
    }
}

OVER

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/379026.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

umi 中如何使用 px2rem 插件做rem适配

umi 中如何使用 px2rem 插件做rem适配在umi的src下面创建两个文件app.ts和document.ejs下载lib-flexible和postcss-px2rem-exclude在.umirc.ts文件中进行配置和postcss-px2rem-exclude的引入在app.ts文件中引入lib-flexible如果px2rem配置无法生效&#xff0c;那么我们就要在do…

Javascript的API基本内容(五)

一、js组成 JavaScript的组成 ECMAScript: 规定了js基础语法核心知识。 比如&#xff1a;变量、分支语句、循环语句、对象等等 Web APIs : DOM 文档对象模型&#xff0c; 定义了一套操作HTML文档的API BOM 浏览器对象模型&#xff0c;定义了一套操作浏览器窗口的API 二、loc…

JavaScript从零开始 学习记录(二)

前言 寒假花了大气力去整理公众号&#xff0c;因而一些任务没有完成&#xff0c;但没有关系&#xff0c;毕竟计划赶不上变化&#xff0c;接着学习&#xff0c;争取早日开发油猴脚本 笔记范围 从这节视频到那节视频结束 课程目标 能够知道为什么要有数组能够创建数组能够获…

“来源可靠、程序规范、要素合规”与“四性”

《从技术可行性的视角看电子档案的“四性”》一文中已经明确&#xff0c;笔者认为的电子档案“四性”是指“真实性、完整性、可用性和安全性”。而《从特斯拉“刹车失灵”事件看电子档案的法定要求》一文中&#xff0c;笔者对于“来源可靠、程序规范、要素合规”的解读如下&…

Qt基础之三十:百万级任务并发处理

在实际的开发过程中,经常会遇到要处理大量任务场景,比如说压缩文件夹中的所有文件、对文件夹中的所有文件加密、上传文件夹中的所有文件到ftp等等。这里说百万级并不夸张,理论上文件夹中有任意多个文件都是可以的。 本文以压缩文件夹中的100万张jpg图片为例,压缩工具使用的…

外卖扫码点餐系统源码 后台管理端+商家端+门店端+小程序用户端源码

外卖点餐 堂食点餐 扫码点餐 本套扫码点餐系统源码基于java语言开发&#xff0c;移动端原生小程序&#xff0c;SaaS模式。代码完整&#xff0c;带部署调试视频。 系统由总后台管理端商家端门店端小程序用户端组成&#xff0c;支持扫码点单、计费结账、出菜上菜、菜品管理、菜…

【办公类-19-02】办公中的思考——Python批量制作word文本框的名字小标签,用A4word打印(植物角、家长会、值日生)

背景需求&#xff1a; 2月28日去小班带班&#xff0c;看到班主任制作了一些小手印花束作为家长会的家长座位提示&#xff0c;上面贴着“”圆形白色的幼儿名字贴”。 我立刻想起了制作的过程——在word中插入文本框&#xff0c;然后复制无数个文本框&#xff0c;摆好位置&#…

【AI绘画】绝美春天插画,人人都是插画师

春天&#xff0c;自然界重新苏醒&#xff0c;生机勃勃&#xff0c;百花争艳&#xff0c;万籁俱寂。一切都被新的生命活力所染上。春风拂面&#xff0c;一股清新的空气流过&#xff0c;仿佛带着一种神秘的力量&#xff0c;让人心旷神怡&#xff0c;心情舒畅、轻松愉悦。 突然&a…

549、RocketMQ详细入门教程系列 -【消息队列之 RocketMQ(三)】 2023.02.28

目录一、Spring 整合 RocketMQ1.1 消息生产者1.2 消息消费者1.3 Spring 配置文件1.4 运行实例程序二、参考链接一、Spring 整合 RocketMQ 不同于 RabbitMQ、ActiveMQ、Kafka 等消息中间件&#xff0c;Spring 社区已经通过多种方式提供了对这些中间件产品集成&#xff0c;例如通…

WebRTC Opus编码器的创建与参数细节分析( sdp -> native )

这几天在做一些WebRTC音频改进方面的调查工作&#xff0c;在阅读Chromium源码的过程中&#xff0c;就顺便记录下来&#xff0c;便于日后回顾。本文基于Chromium 85源码分析&#xff0c;由于Chromium的快速发展&#xff0c;很有可能不适合于跨度太大的Chromium版本。大家知道Opu…

QT学习14:QtXlsx操作Excel表

一、前言操作excel方式有&#xff1a;QAxObject 和QtXlsx区别&#xff1a;Qt自带的QAxObject库操作excel的前提是电脑已经安装微软的Office&#xff08;包含EXCEL&#xff09;&#xff0c;而QtXlsx可以直接使用免装Office且操作更简单。二、QtXlsx操作示例参考&#xff1a;http…

C筑基——深入理解内存对齐

目录1 前言2 正文2.1 为什么要有内存对齐&#xff1f;2.2 内存对齐原则2.2.1 基本数据类型是自然对齐的2.2.2 包含基本数据类型成员的结构体套用结构体内存对齐原则来分析使用 gdb 查看这两个结构体的成员内存位置结构体类型变量是自然对齐的吗&#xff1f;2.2.3 数组类型2.3 修…

今天 4 点,龙蜥自动化运维平台SysOM 2.0的诊断中心功能介绍 | 第 66-68 期

本周 3 期「龙蜥大讲堂」预告来啦&#xff01;我们邀请了系统运维 SIG Contributor 阙建明分享《SysOM 2.0 诊断中心功能介绍》&#xff0c;龙蜥社区云原生机密计算 SIG Maintainer、Intel 高级云计算软件工程师黄晓军分享《Intel HE Toolkit 介绍》主题演讲&#xff0c;龙蜥社…

【Linux】操作系统与Linux — Linux概述、组成及目录结构

目录 一、什么是操作系统&#xff1f;都有那些&#xff1f; 二、Linux概述 三、Linux组成 三、Linux目录结构 四、Linux目录结构 &#x1f49f; 创作不易&#xff0c;不妨点赞&#x1f49a;评论❤️收藏&#x1f499;一下 一、什么是操作系统&#xff1f;都有那些&#x…

频率信号转电压或电流信号隔离变送器0-1KHz /0-5KHz /0-10KHz转0-2.5V/0-5V/0-20mA

主要特性:>> 精度等级&#xff1a;0.2级>> 全量程内极高的线性度&#xff08;非线性度<0.1%&#xff09; >> 辅助电源/信号输入/信号输出&#xff1a; 2500VDC 三隔离>> 辅助电源&#xff1a;5VDC&#xff0c;12VDC&#xff0c;24VDC等单电源供电&g…

2020蓝桥杯真题约数个数(填空题) C语言/C++

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 1200000 有多少个约数&#xff08;只计算正约数&#xff09;。 运行限制 最大运行时间&#xff1a;1s 最大运行内存: 128M 所需变量 int a 1200000;//初始最大数 i…

模式识别 —— 第一章 贝叶斯决策理论

模式识别 —— 第一章 贝叶斯决策理论 前言 新的学期开始了&#xff0c;当然是要给不爱吃香菜的月亮记录学习笔记呀~ 没多久了&#xff0c;待夏花绚烂之时~人山人海&#xff0c;我们如约而至&#xff01; 以后清河海风 溶溶月色 共赏之人 就在身侧 mua~ 文章目录模式识别 —…

【服务器数据恢复】HP EVA存储lun丢失的数据恢复案例

服务器故障&检测&分析&#xff1a; 某品牌EVA存储设备中的RAID5磁盘有两块硬盘掉线&#xff0c;lun丢失。硬件工程师对故障服务器进行物理故障检测&#xff0c;发现掉线硬盘能够正常读取&#xff0c;无物理故障&#xff0c;也没有发现坏道。 故障服务器掉线硬盘没有物理…

深度理解Redux原理并实现一个redux

Redux的作用是什么 Redux的作用在于实现状态传递、状态管理。在这里你可能会说了&#xff0c;如果是状态传递&#xff0c;那我props的传递不也是可以达到这样的效果吗&#xff1f;context上下文方案不也是可以达到这样的效果吗&#xff1f;没错&#xff0c;是这样的&#xff0…

汇川SV660N与基恩士 KV7500 控制器调试说明

1. 伺服相关部分配置 1.1 伺服相关版本 SV660N 试机建议使用“SV660N-Ecat_v0.09.xml”及以上设备描述文件。 SV660N 单板软件版本建议为“H0100901.4”及更高版本号。 1.2 相关参数说明 SV660N 对象字典中 60FD 的含义较 IS620N 有所更改&#xff1a;bit0、1、2 分别为负限位…