Builder设计模式构建通用型Dialog

article/2025/8/27 19:45:30

目录

写在前面

一、什么是Builder模式

二、AlertDialog源码分析

2.1、源码阅读

2.2、Builder模式工作流程

三、代码实战——Builder模式构建通用型Dialog

3.1、基本框架搭建

3.2、完善Builder

3.3、完善真正的构建器

3.4、自定义参数配置

四、使用Dialog


写在前面

最近在看辉哥的视频,看到视频里他写Dialog的方式,又想到了自己写的,瞬间觉得尴尬无比,自己的代码真的就像一坨XIANG!不说了,这是辉哥的简书地址:https://www.jianshu.com/u/35083fcb7747,有兴趣的可以加波关注,反正我是对他佩服的五体投地,不只是写代码哦,各方面都是!

再回到本篇中来,不知不觉又快到五一了,天气好自然而然的心情也变好了,这么好的天气不撸代码真的可惜了,于是乎就把辉哥视频中讲的内容自己跟着搞了一把,就有了今天这一篇——建造者模式构建万能Dialog了!看过我博客的小伙伴们应该都还记得关于Dialog的使用,我之前也是写过的,而且还写了两篇,有兴趣的可以看一下:

  1. Android自定义通用的Dialog:https://blog.csdn.net/JArchie520/article/details/79157471
  2. Android自定义View之通用Dialog:https://blog.csdn.net/JArchie520/article/details/103454231

对于Dialog的使用没有任何的难度,但是如何让你写的Dialog功能上更加通用,架构设计上更加简洁并且具有可扩展性,这就需要你认真的思考了,大家看我之前写的两篇就能够看出代码层次上也是一次比一次清晰,易用性一次比一次要好,虽然很low,但是也说明了咱也是在不断进步的对吧,那为了更加易用,程序的可移植性更好,我决定继续对它改造升级和优化,结合设计模式来封装一个通用型的Dialog,之所以选择Builder设计模式,是因为系统的AlertDialog也是采用这种模式来实现的,可以链式调用非常方便。

效果展示:

一、什么是Builder模式

定义:将一个复杂对象的构建与它的表示分离,使得不同的构建过程可以创建不同的显示,但其根本还是不变。

使用场景:

  • ①、相同的方法,不同的执行顺序,产生不同的事件结果时;
  • ②、多个部件或零件都可以装配到一个对象中,但是产生的运行结果又不相同时;
  • ③、产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能时;

二、AlertDialog源码分析

2.1、源码阅读

既然我们要采用构建者模式来实现一个Dialog,又因为Android系统的AlertDialog就是采用构建者模式来实现的,那这一部分就先来看下谷歌的大神们是如何实现的?下面这行代码是我们在应用层最简单的一个api调用了,接下来我们就按照这行代码来依次去到Android系统的源码中查看一下底层是如何实现的:

new AlertDialog.Builder(this).setTitle("测试").setIcon(R.mipmap.ic_launcher).create().show();

以下源码基于Android6.0源码分析:文件目录:frameworks/base/core/java/android/app/AlertDialog.java(不要找错了)

首先进入AlertDialog类中,可以看到它的构造方法是protected类型的,这也就意味着你不能直接去new一个AlertDialog对象:

protected AlertDialog(Context context) {this(context, 0);
}

它是通过一个内部类Builder在构造方法中new了一个对象P,它是AlertController类的一个静态内部类对象AlertParams:

public Builder(Context context, int themeResId) {private final AlertController.AlertParams P;P = new AlertController.AlertParams(new ContextThemeWrapper(context, resolveDialogTheme(context, themeResId)));
}

然后我们再来看一下setTitle()、setIcon()这些方法又是做了什么?

public Builder setTitle(@StringRes int titleId) {P.mTitle = P.mContext.getText(titleId);return this;
}
public Builder setIcon(Drawable icon) {P.mIcon = icon;return this;
}

从这个代码中可以看出,这些set方法其实就是给P对象内部去放置一些参数,然后返回Builder自身,也就是这里的this。

然后接着看create()方法又做了些什么?

public AlertDialog create() {// Context has already been wrapped with the appropriate theme.final AlertDialog dialog = new AlertDialog(P.mContext, 0, false);P.apply(dialog.mAlert);...省略部分代码        
}

这个方法中首先就是new了一个Dialog,然后通过P调用了一个apply方法,到这一步就是设置参数了,把Dialog中的参数都从P里面拿,现在跟到这个apply方法中看一下:

public void apply(AlertController dialog) {if (mCustomTitleView != null) {dialog.setCustomTitle(mCustomTitleView);} else {if (mTitle != null) {dialog.setTitle(mTitle);}if (mIcon != null) {dialog.setIcon(mIcon);}if (mIconId != 0) {dialog.setIcon(mIconId);}if (mIconAttrId != 0) {dialog.setIcon(dialog.getIconAttributeResId(mIconAttrId));}}...省略一大串代码
}

可以看到在这里就是开始组装P内部的一系列参数,有什么就拼装什么,里面有一系列的if判断。

最后是调用了Dialog的show()方法去展示,这个show注意是在Dialog中的,因为AlertDialog是继承自Dialog的,这个源码就不再贴了,里面的实现还是比较复杂的,涉及到了Window对象的一些概念,有兴趣的可以研究研究,因为不是本篇的重点,所以就不多说了。

2.2、Builder模式工作流程

添加参数(P)--->组装参数(添加多少就组装多少)--->显示

主要涉及的对象:

  • AlertDialog:整体的弹出框对象
  • AlertDialog.Builder:规范一系列的组装过程
  • AlertController:具体的构建器
  • AlertController.AlertParams:存放参数以及一部分设置参数的功能

三、代码实战——Builder模式构建通用型Dialog

3.1、基本框架搭建

从这里开始我们就来封装这个通用型Dialog了,首先仿照源码把基本框架搭建起来,我们先来创建一个类CommonDialog让它继承自Dialog,以及它的内部类Builder,这些代码都是仿照源码来写的,其中有些代码是直接从源码中拷贝过来然后修改的:

/*** 作者: 乔布奇* 日期: 2020-04-26 22:42* 邮箱: jarchie520@gmail.com* 描述: 自定义通用型Dialog*/
public class CommonDialog extends Dialog {private CommonController mController;public CommonDialog(@NonNull Context context, int themeResId) {super(context, themeResId);mController = new CommonController(this,getWindow());}//创建内部类构建器public static class Builder{private final CommonController.CommonParams P;public Builder(Context context){this(context, R.style.dialog);}public Builder(Context context,int themeId){P = new CommonController.CommonParams(context,themeId);}public CommonDialog create(){// Context has already been wrapped with the appropriate theme.final CommonDialog dialog = new CommonDialog(P.mContext,P.mThemeResId);P.apply(dialog.mController);dialog.setCancelable(P.mCancelable);if (P.mCancelable) {dialog.setCanceledOnTouchOutside(true);}dialog.setOnCancelListener(P.mOnCancelListener);dialog.setOnDismissListener(P.mOnDismissListener);if (P.mOnKeyListener != null) {dialog.setOnKeyListener(P.mOnKeyListener);}return dialog;}public CommonDialog show(){final CommonDialog dialog = create();dialog.show();return dialog;}}
}

这里给它一个默认的style,也就是在Builder的构造方法中设置的这个R.style.dialog,主题的代码如下:

    <style name="dialog" parent="@android:style/Theme.Dialog"><!--边框--><item name="android:windowFrame">@null</item><!--是否浮现在Activity之上--><item name="android:windowIsFloating">true</item><!--背景透明--><item name="android:windowBackground">@android:color/transparent</item><!--模糊--><item name="android:backgroundDimEnabled">true</item><!--无标题--><item name="android:windowNoTitle">true</item></style>

然后接着创建Builder中的Dialog的构建器类CommonController以及它的构建参数的内部类CommonParams

/*** 作者: 乔布奇* 日期: 2020-04-26 22:43* 邮箱: jarchie520@gmail.com* 描述: 通用型Dialog构建器*/
class CommonController {private CommonDialog mDialog;private Window mWindow;public CommonController(CommonDialog dialog, Window window) {this.mDialog = dialog;this.mWindow = window;}//获取Dialogpublic CommonDialog getDialog(){return mDialog;}//获取Dialog的Window对象public Window getWindow() {return mWindow;}public static class CommonParams {public Context mContext;public int mThemeResId;//点击空白是否能够取消public boolean mCancelable = false;//dialog Cancel监听public DialogInterface.OnCancelListener mOnCancelListener;//dialog Dismiss监听public DialogInterface.OnDismissListener mOnDismissListener;//dialog Key监听public DialogInterface.OnKeyListener mOnKeyListener;public CommonParams(Context context, int themeResId) {this.mContext = context;this.mThemeResId = themeResId;}/*** 绑定和设置参数* @param mController*/public void apply(CommonController mController) {}}
}

这里面的变量及事件监听都是仿照源码来的,拷贝修改就OK了,这样最基本的架子就先搭建起来了!

3.2、完善Builder

这一部分我们来给Builder类的内部添加一系列的setXXX()方法,比如系统Dialog中的设置标题图标这些东西,这些设置的方法都是一些套路代码,定义一个方法,返回值类型为Builder,方法内部进行设置操作,最后返回this即可。

首先我们需要在CommonController中的CommonParams类中添加几个需要用到的变量:

//布局View
public View mView;
//布局Layout ID
public int mViewLayoutResId;
//存放文本的修改,文本可能有多个,需要使用Map存储,这里选择SparseArray因为它更加高效
public SparseArray<CharSequence> mTextArray = new SparseArray<>();
//存放点击事件
public SparseArray<View.OnClickListener> mClickArray = new SparseArray<>();

这里需要注意的点我也在代码注释中写了,因为我们的Dialog可能是各式各样的,所以对于文本和点击事件的设置都是不可控的,无法确定数量上有多少,位置上在哪里点击,所以这里需要采用Map集合去存储这种多个的情况,又因为我们都是通过控件id去操作文本及点击事件的,它符合HashMap<Integer,Object>这种int--->Object的格式,所以这里选择使用SparseArray<T>去存储,它比Map在性能上更加高效。

然后就是Builder中的一系列设置操作了:

        //设置布局Viewpublic Builder setContentView(View view){P.mView = view;P.mViewLayoutResId = 0;return this;}//设置布局内容LayoutIdpublic Builder setContentView(int layoutId){P.mView = null;P.mViewLayoutResId = layoutId;return this;}//设置文本public Builder setText(int viewId,CharSequence text){P.mTextArray.put(viewId,text);return this;}//设置点击事件public Builder setOnClickListener(int viewId,View.OnClickListener listener){P.mClickArray.put(viewId,listener);return this;}//设置是否可以取消public Builder setCancelable(boolean cancelable) {P.mCancelable = cancelable;return this;}//设置Cancel监听public Builder setOnCancelListener(OnCancelListener onCancelListener) {P.mOnCancelListener = onCancelListener;return this;}//设置Dismiss监听public Builder setOnDismissListener(OnDismissListener onDismissListener) {P.mOnDismissListener = onDismissListener;return this;}//设置key监听public Builder setOnKeyListener(OnKeyListener onKeyListener) {P.mOnKeyListener = onKeyListener;return this;}

3.3、完善真正的构建器

在上面分析源码的时候我们说过,真正的设置参数的操作是P对象调用apply()方法实现的:P.apply(dialog.mAlert),那接下来就来写我们自己的这个apply()方法,在写之前我们先定义一个DialogViewHelper类用于View的辅助处理:

/*** 作者: 乔布奇* 日期: 2020-04-26 22:44* 邮箱: jarchie520@gmail.com* 描述: Dialog View的辅助处理类*/
class DialogViewHelper {private View mContentView = null;//WeakReference防止内存泄漏private SparseArray<WeakReference<View>> mViews;public DialogViewHelper(Context context, int layoutResId) {this();mContentView = LayoutInflater.from(context).inflate(layoutResId, null);}public DialogViewHelper() {mViews = new SparseArray<>();}//设置布局public void setContentView(View contentView) {this.mContentView = contentView;}//设置文本public void setText(int viewId, CharSequence text) {TextView textView = getView(viewId);if (textView != null) {textView.setText(text);}}//设置点击事件public void setOnclickListener(int viewId, View.OnClickListener listener) {View view = getView(viewId);if (view != null) {view.setOnClickListener(listener);}}//获取ContentViewpublic View getContentView() {return mContentView;}//通用fv获取控件private <T extends View> T getView(int viewId) {WeakReference<View> viewReference = mViews.get(viewId);View view = null;if (viewReference != null) {view = viewReference.get();}if (view == null) {view = mContentView.findViewById(viewId);if (view != null) {mViews.put(viewId, new WeakReference<>(view));}}return (T) view;}
}

这里需要注意的点是我们定义了一个通用的防止重复绑定控件的方法,已经绑定过的不用再次通过findViewById获取了,直接从弱引用中拿就行,定义好了这个类,我们就可以先来填充apply方法了,先让我们的Dialog显示出来:

        /*** 绑定和设置参数** @param mController*/public void apply(CommonController mController) {DialogViewHelper viewHelper = null;//设置Dialog的布局if (mViewLayoutResId != 0) {viewHelper = new DialogViewHelper(mContext, mViewLayoutResId);}if (mView != null) {viewHelper = new DialogViewHelper();viewHelper.setContentView(mView);}if (viewHelper == null){throw new IllegalArgumentException("请设置布局setContentView()");}//给Dialog设置布局mController.getDialog().setContentView(viewHelper.getContentView());//设置文本int textArraySize = mTextArray.size();for (int i=0;i<textArraySize;i++){viewHelper.setText(mTextArray.keyAt(i),mTextArray.valueAt(i));}//设置点击事件int clickArraySize = mClickArray.size();for (int i=0;i<textArraySize;i++){viewHelper.setOnclickListener(mClickArray.keyAt(i),mClickArray.valueAt(i));}}

OK,到这里其实我们的Dialog就已经能够显示出来了,只不过还有很多细节需要处理,来继续往下看吧!

3.4、自定义参数配置

首先我们在CommonController的内部类CommonParams中添加我们需要的自定义参数:

//宽度
public int mWidth = ViewGroup.LayoutParams.WRAP_CONTENT;
//动画
public int mAnimations = 0;
//位置
public int mGravity = Gravity.CENTER;
//高度
public int mHeight = ViewGroup.LayoutParams.WRAP_CONTENT;

然后在Builder中对添加的这些变量同样的去赋值也即是set操作,这里的dialog_scale_anim就是一个简单的缩放动画:

        //配置一些通用参数public Builder fullWidth(){P.mWidth = ViewGroup.LayoutParams.MATCH_PARENT;return this;}//从底部弹出,是否有动画public Builder fromBottom(boolean isAnimation){if (isAnimation){P.mAnimations = R.style.dialog_from_bottom_anim;}P.mGravity = Gravity.BOTTOM;return this;}//设置宽高public Builder setWidthAndHeight(int width,int height){P.mWidth = width;P.mHeight = height;return this;}//添加默认动画public Builder addDefaultAnimation(){P.mAnimations = R.style.dialog_scale_anim;return this;}//自行设置动画public Builder setAnimations(int styleAnimation){P.mAnimations = styleAnimation;return this;}

最后在apply()方法中进行配置,这里就要用到我们的Window对象了:

//配置自定义效果:全屏,从底部弹出,动画等
Window window = mController.getWindow();
//设置位置
window.setGravity(mGravity);
//设置动画
if (mAnimations != 0) {window.setWindowAnimations(mAnimations);
}
//设置宽高
WindowManager.LayoutParams params = window.getAttributes();
params.width = mWidth;
params.height = mHeight;
window.setAttributes(params);

OK,到这里我们的dialog基本上就已经搞定了,后续你如果需要进行相关的拓展,直接添加你需要的属性就OK了。好,写了这么多,你会觉得这不是更加复杂了吗?是吗?造轮子的过程是比较复杂,但是用轮子的时候可不复杂哦,甚至你还会偷着乐,下面就让我们一起来看一下调用的时候是不是变得相当简单了呢?

四、使用Dialog

我们先来看一个最简单的情况,比如我们有些场景下会弹出一些⚠️警告提示之类的Dialog,这种直接给用户看的,无需操作:

先来自定义一个Dialog的布局dialog_test_1.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="300dp"android:layout_height="wrap_content"android:background="@color/color_white"android:orientation="vertical"><ImageViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/ic_launcher_round"android:layout_gravity="center_horizontal"android:layout_marginTop="10dp"/><TextViewandroid:id="@+id/mContent"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:gravity="center"android:lineSpacingExtra="3dp"android:paddingLeft="10dp"android:paddingRight="10dp"android:layout_marginBottom="20dp"android:text="我是弹出内容"android:textColor="@color/colorPrimary"android:textSize="16sp" /></LinearLayout>

一个图片一个文本,这是很简单的一个场景了,这种调用就很爽了,一直往下点就行了:

new CommonDialog.Builder(MainActivity.this).setContentView(R.layout.dialog_test_1).setWidthAndHeight(DensityUtil.dp2px(300), LinearLayout.LayoutParams.WRAP_CONTENT).addDefaultAnimation().create().show();

就是这么直接,就是这么简单,一行(如果你的屏幕足够宽)下来搞定!

再来看一个有用户交互的场景,带有确认取消按钮的,同样的我们创建一个dialog_test_0.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="300dp"android:layout_height="wrap_content"android:background="@color/color_white"android:orientation="vertical"><TextViewandroid:id="@+id/mTitle"android:layout_width="match_parent"android:layout_height="45dp"android:gravity="center"android:text="我是标题"android:textColor="@color/colorAccent"android:textSize="18sp" /><TextViewandroid:id="@+id/mContent"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:gravity="center"android:lineSpacingExtra="3dp"android:paddingLeft="10dp"android:paddingRight="10dp"android:text="Android自定义View,Android JetPack,常用第三方库源码,Android Framework源码,C/C++/JNI/NDK,MVC/MVP/MVVM/模块化/组件化/插件化,热更新热修复,设计模式,线程间通信,进程间通信"android:textColor="@color/colorPrimary"android:textSize="16sp" /><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:layout_marginTop="10dp"android:background="@color/colorE9" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="45dp"android:background="@color/colorE9"android:orientation="horizontal"><TextViewandroid:id="@+id/mCancel"android:layout_width="0dp"android:layout_height="match_parent"android:layout_marginRight="1dp"android:layout_weight="1"android:background="@color/color_white"android:gravity="center"android:text="取消"android:textColor="@color/color_666"android:textSize="18sp" /><TextViewandroid:id="@+id/mConfirm"android:layout_width="0dp"android:layout_height="match_parent"android:layout_marginLeft="1dp"android:layout_weight="1"android:background="@color/color_white"android:gravity="center"android:text="确认"android:textColor="@color/colorAccent"android:textSize="18sp" /></LinearLayout>
</LinearLayout>

然后在Java代码中调用,这里考虑到某些场景下需要拿到相关的数据,所以将点击事件在Dialog中也提供了一份,这样方便我们进行一些数据处理的操作,所以最后的调用成了这个样子:

CommonDialog dialog = new CommonDialog.Builder(MainActivity.this).setContentView(R.layout.dialog_test_0).setCancelable(true).fromBottom(true).fullWidth().setText(R.id.mTitle,"Android高级进阶").create();
dialog.setOnclickListener(R.id.mConfirm, v -> {Toast.makeText(MainActivity.this,"点击确定了",Toast.LENGTH_SHORT).show();dialog.dismiss();
});
dialog.setOnclickListener(R.id.mCancel, v -> {Toast.makeText(MainActivity.this,"点击取消了",Toast.LENGTH_SHORT).show();dialog.dismiss();
});
dialog.show();

其实跟上面的也是差不多的,没有太大的区别,代码稍作改动即可,最后我会把完整的代码贴出来供大家参考!

写到这里基本上就要和大家说再见了,如有问题,欢迎留言或者私信我进行探讨!因为我本人比较懒,所以没有新建项目,我直接在把代码封装了一个lib_common放到了我之前写的《Android架构设计之MVC/MVP/MVVM浅析》的源码中了,有需要的可以下载或者clone!

源码:https://github.com/JArchie/MVXProject


http://chatgpt.dhexx.cn/article/Y5ZYQ0MZ.shtml

相关文章

自学鸿蒙应用开发(26)- 自定义CommonDialog

执行效果 上一篇文章中说过&#xff0c;直接使用鸿蒙系统中的CommonDialog大致是下面的效果&#xff1a; 这个效果实在是无法用于实际的应用开发。本文介绍如何定制自己的CommonDialog。还是先看演示视频&#xff1a; CustomizeCommonDialog 准备布局 定制CommonDialog的第一…

Android炫酷翻转Dialog及高仿苹果IOS的Dialog

简单的Android弹出Dialog效果&#xff08;圆角&#xff09; 最近一段时间工作挺忙的&#xff0c;一直想写一篇博文&#xff0c;总是被各种事情打破计划&#xff0c;终于这次利用这个周末来开始自己第一次的技术文章的写作&#xff0c;提前说明&#xff0c;本人还是个菜鸟&#…

Android 全局Dialog

前沿 android 弹窗好几种&#xff0c;全局弹窗是什么&#xff1f;和普通Dialog&#xff08;必须依附activity上下文的弹窗&#xff09;有什么区别&#xff1f; 逛技术blog发现【全局dialog】这个名词&#xff0c;之前用FragmentDialog&#xff0c;自定义dialog。以及dialog的…

Android开发dialog内存泄露,Android中导致内存泄漏的竟然是它----Dialog

一. 内存泄漏的 Bug 猛增 最近在 App 进行 mokey 测试的时候检测到一些内存泄漏问题。在前天的测试中,楼主一瞬间收到了4个这样的 Bug 单,瞬间心理无比纠结,真有千万只羊驼向我奔来。 登录页面出现内存泄漏??!!楼主的代码是如此的***而无懈可击,这么可能出现这么多泄漏的…

dialog.setOnDismissListener(null)过程分析

前提 为解决DialogFragment的内存泄漏&#xff0c;使用了此篇博客的处理方法 DialogFragment 内存泄露&#xff0c;简单说就是给 dialog 设置 getDialog().setOnCancelListener(null); getDialog().setOnDismissListener(null);但发现了一个问题&#xff0c;当用户返回Activi…

深入分析Android中Dialog

在Android中,Dialog是一个非常重要的UI, 它可以方便的给用户提示,用最简洁的方式向用户展示信息, 以下的图片是Dialog的一个整体架构&#xff0c;通过它&#xff0c;可以总体对Dialog有一个很清晰的认识. 从这张图中可以看到&#xff0c;Dialog为父类, 其下有最重要的&#xf…

android自定义dialog去除title,Android 自定义Dialog去除title导航栏的解决方法

Android 自定义Dialog去除title导航栏的解决方法 如下所示: Dialog dialog = new Dialog(context); dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); dialog.setContentView(view); 以上这篇Android 自定义Dialog去除title导航栏的解决方法就是小编分享给大家的全部内…

android常见的dialog的使用及认识

介绍 在实际开发过程中 , 我们难免要经常使用提示框 (dialog), 根据不同的场景使用不同的样式的提示框(dialog). androd提供了丰富的dialog函数 , 本文将介绍在实际开发中经常使用的对话框, 包括普通对话框 , 列表对话框 , 单选对话框 , 多选对话框 , 等待对话框, 进度条对话框…

ABAP屏幕设计Dialog

目录 一、概览 1.屏幕 2.程序组织 3.屏幕定义和维护 用途&#xff1a; 组成&#xff1a; Dialog的屏幕执行过程&#xff1a; 属性&#xff1a; 创建&#xff1a; 4.屏幕属性的动态修改 5.屏幕序列 二、Screen编程实例 1.Hello World屏幕编程 建立程序&#xff1a; 设计…

Android Dialog 源码研究

Android Dialog 源码研究 在阅读Dialog源代码之前,我给自己提出了4个问题,带着这4个问题的疑问,我才开始看源码,这样的好处能让阅读中有了侧重点,往往能更快的理解某些代码的意图,这也正是为什么总说提出问题本身,要比解决问题困难。 我下面要思考的4个问题是: Dialo…

android 判断dialog,Android 7.0经验谈:Dialog不显示之迷

最近遇到个怪问题,在其他手机上都能正常的显示Dialog,但是在Android 7.0的手机上只能显示Dialog的半透明背景,无法显示Dialog的内容。 用图给大家展示一个遇到的现象,正常时应该是这个样子的: 而我们遇到的情况如下,更坏的是如果我们设置Dialog不能点击空白处取消(dismis…

Android窗口设计之Dialog、PopupWindow、系统窗口的实现

窗口设计之Dialog、PopupWindow、系统窗口的实现 Android应用程序窗口设计系列博客: Android应用程序窗口设计之Window及WindowManager的创建 Android应用程序窗口设计之setContentView布局加载的实现 普法Android的Token前世今生以及在APP,AMS,WMS之间传递 Android应用程序窗口…

理解Android中Dialog

文章收藏的好句子&#xff1a;你能走多远、爬多高&#xff0c;不仅取决于你自身的力量&#xff0c;还取决于周围人带动的力量。 PS&#xff1a;本文是基于 Android Api 26 来分析源码的。 1、Dialog 的 Window 是在哪里创建的&#xff1f; Dialog 的 Window 是在什么地方创建的…

Android之Dialog分析

Android之Dialog分析 以Dialog为引导&#xff0c;Android的弹出式消息一共是三种&#xff08;据我所知&#xff09;&#xff1a;Dialog&#xff0c;tocast&#xff0c;notification 其三种弹出式消息各有所长。今天重点是分析其中的Dialog。Android的Dialog是android界面编程的…

Android开发dialog内存泄露,Dialog引发的内存泄漏

8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 本文是本人对于 LeakCanary 团队的一篇分析内存泄漏的文章的意译。水平有限,如有不够准确之处,敬请包涵。 主旨:在Lollipop之前的版本,Dialog可能导致内存泄漏。 引言 LeakCanary 提示存在内…

android源码分析-Dialog

今天给大家介绍android -Dialog源码分析 Dialog 是所有对话框的基类&#xff0c;例如AlertDialog&#xff0c;我们要深入了解指导Dialog的用法&#xff0c;逻辑&#xff0c;必须要把Dilaog弄清楚&#xff0c;下面首先我们来看下Google对Dialog的类描述&#xff1a;/**Base clas…

Dialog源码分析

1, 概述 Dialog(对话框)不仅可以显示信息,还可以和Activity界面进行交互,这种交互是阻塞式的. 继承Dialog的类有好几种,主要以AlertDialog为例来分析一下具体的原理。 2 实现 Dialog依附于Activity来实现,一般在acitivty中显示,因为Dialog的交互是阻塞式的,所以最好另开一线…

爬虫为什么会使用到HTTP代理?

在进行网页爬虫的时候使用HTTP代理&#xff0c;可以进行匿名抓取网页信息&#xff0c;爬取大数据等使用方向。HTTP代理我们很了解&#xff0c;但是你有了解过HTTP协议是什么吗&#xff1f; HTTP协议即超文本传输协议&#xff0c;是Internet上信息传输时使用最为广泛的一种简单…

爬虫笔记——全局代理下的requests写法

当PC挂了全局代理的时候&#xff0c;如果你的requests还像下面写的话&#xff0c;大概率会报错&#xff1a; 正确的写法是&#xff1a;

抓包:Android不走代理的请求

测试用例 测试应用有两个按钮&#xff0c;分别用 HttpURLConnection 和 Okhttp3 请求 https://www.baidu.com/。注意&#xff1a;两个请求都加入了 Proxy.NO_PROXY。 //HttpURLConnection请求https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel13812371237 public …