首页 文章 精选 留言 我的

精选列表

搜索[渲染问题],共10000篇文章
优秀的个人博客,低调大师

Toast在子线程调用的问题

Toast我们平时经常使用,但是你是否了解在子线程中要如何使用Toast呢? Toast的一般姿势 平时我们经常在主线程中直接使用Toast,代码看起来会像下面这样 Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT).show(); 但是如果在子线程调用是不会有toast弹出的 Toast的正确姿势 如果在子线程调用那么让Toast能正常显示的方式是在它之前和之后调用Looper.prepare()和Looper.loop() Looper.prepare(); Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT).show(); Looper.loop(); 原因是什么呢 我们得从源码角度来分析,看看在Toast show()的时候做了些什么 public void show() { if (mNextView == null) { throw new RuntimeException("setView must have been called"); } INotificationManager service = getService(); String pkg = mContext.getOpPackageName(); TN tn = mTN; tn.mNextView = mNextView; try { service.enqueueToast(pkg, tn, mDuration); } catch (RemoteException e) { // Empty } } 所以Toast其实是通过NotificationManagerService来实现Toast的展示的,而传给他的参数里的 mTn又是什么呢, 其实它是Toast的一个内部类,它有两个方法,show()和hide()是用来给NotificationManagerService回调的,可以看看它的代码 private static class TN extends ITransientNotification.Stub { .... /** * schedule handleShow into the right thread */ @Override public void show(IBinder windowToken) { if (localLOGV) Log.v(TAG, "SHOW: " + this); mHandler.obtainMessage(SHOW, windowToken).sendToTarget(); } /** * schedule handleHide into the right thread */ @Override public void hide() { if (localLOGV) Log.v(TAG, "HIDE: " + this); mHandler.obtainMessage(HIDE).sendToTarget(); } 因此可以看出来,Toast通过 NotificationManagerService来统一调度 Toast,而 NotificationManagerService回调 TN 的show()来往对应的线程发消息, 既然是handler实现,那么来看看它的实现代码,就在TN的构造方法里有这么一段 if (looper == null) { // Use Looper.myLooper() if looper is not specified. looper = Looper.myLooper(); if (looper == null) { throw new RuntimeException( "Can't toast on a thread that has not called Looper.prepare()"); } } mHandler = new Handler(looper, null) {.... 因此没有调用prepare()和启动消息队列的话,在子线程调用Toast是显示不出来的。 总结 Toast在主线程的显示只需要调用show()就可以,如果想在子线程调用,则需要在子线程启动Looper,这样才能有消息队列来承载Handler收发消息。否则子线程的Toast是不能显示的 更多Android进阶技术,面试资料系统整理分享,职业生涯规划,产品,思维,行业观察,谈天说地。可以加Android架构师群;701740775。

优秀的个人博客,低调大师

Android几行代码解决键盘遮挡问题

GitHub APK 将libray模块复制到项目中,或者直接在build.gradle中依赖: allprojects { repositories { maven { url 'https://jitpack.io' } } } dependencies { compile 'com.github.AnJiaoDe:Keyboard:V1.0.0' } 注意:如果sync报错,是因为和com.android.tools.build:gradle 3.0有关,可以改将compile改为implementation 或者api 1.scrollTo、scrollBy实现键盘不遮挡 使用方法: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <RelativeLayout android:layout_width="match_parent" android:layout_height="44dp" android:background="@color/colorPrimary"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:text="提现" android:textColor="#ffffff" /> </RelativeLayout> <LinearLayout android:id="@+id/layout_content" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#E9F4FB" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="38dp" android:layout_marginLeft="15dp" android:layout_marginRight="15dp" android:gravity="center_vertical" android:orientation="horizontal"> <View android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="15dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="可提余额:" android:textColor="#333333" android:textSize="15sp" /> <TextView android:id="@+id/tv_yue" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="2000.00" android:textColor="#666666" android:textSize="14sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="元" android:textColor="#333333" android:textSize="14sp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="15dp" android:layout_marginTop="20dp" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="手续费(0.6%):" android:textColor="#333333" android:textSize="15sp" /> <TextView android:id="@+id/tv_shouxufei" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="0.00" android:textColor="#666666" android:textSize="14sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="元" android:textColor="#333333" android:textSize="14sp" /> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="15dp" android:layout_marginTop="20dp" android:gravity="center_vertical" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="提现方式:" android:textColor="#333333" android:textSize="15sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="3dp" android:text="支付宝" android:textColor="#666666" android:textSize="14sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="3dp" android:text="银行卡" android:textColor="#666666" android:textSize="14sp" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="20dp" android:background="@color/line" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="11dp" android:gravity="center" android:text="申请提现金额" android:textColor="#333333" android:textSize="15sp" /> <LinearLayout android:id="@+id/layout_et" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="23dp" android:layout_marginRight="23dp" android:layout_marginTop="13dp" android:orientation="vertical"> <View android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> <EditText android:id="@+id/et_jine" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:background="@null" android:gravity="center" android:hint="请输入提现金额" android:inputType="numberDecimal|number" android:maxLength="20" android:minHeight="44dp" android:textColorHint="#999999" android:textSize="14sp" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="30dp" android:background="#A7ABB1" /> </LinearLayout> <Button android:id="@+id/tv_submit" android:layout_width="match_parent" android:layout_height="49dp" android:layout_marginLeft="38dp" android:layout_marginRight="38dp" android:layout_marginTop="33dp" android:gravity="center" android:text="确定" android:textColor="@color/white" android:textSize="16sp" /> </LinearLayout> </LinearLayout> </LinearLayout> public class EditTextActivity extends KeyboardActivity { private View layout_content; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_edit_text); layout_content=findViewById(R.id.layout_content); //设置监听器 setOnCYGlobalLayoutListener(new OnCYGlobalLayoutListener() { //键盘刚显示 @Override public void onKeyboardShowedNow(Rect rect) { //rect 可视区域 //screenHight-rect.bottom就是键盘高度 layout_content.scrollTo(0,screenHight-rect.bottom); } //键盘刚隐藏,可以对输入的内容进行修改 @Override public void onKeyboardHideNow() { layout_content.scrollTo(0,0); } }); } } 2.列表中的Edittext,利用假键盘实现键盘不遮挡 使用方法: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_modify_price2" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <RelativeLayout android:background="@color/colorPrimary" android:layout_width="match_parent" android:layout_height="44dp"> <TextView android:layout_width="match_parent" android:gravity="center" android:layout_height="match_parent" android:text="修改价格" android:textColor="#ffffff" /> </RelativeLayout> <com.cy.cyrvadapter.recyclerview.VerticalRecyclerView android:id="@+id/vrv" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> <View android:id="@+id/view_keyboard" android:layout_width="match_parent" android:layout_height="0dp" /> </LinearLayout> public class RVEdittextActivity extends KeyboardMockActivity { private RVAdapter<String> rvAdapter; private View view_keybord; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_rvedittext); List<String> list = new ArrayList<>(); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); list.add("dojij"); rvAdapter = new RVAdapter<String>(list) { @Override public void bindDataToView(RVViewHolder holder, int position, String bean, boolean isSelected) { } @Override public int getItemLayoutID(int position, String bean) { return R.layout.item_price_modify; } @Override public void onItemClick(int position, String bean) { } }; //万能适配器:https://github.com/AnJiaoDe/RecyclerViewAdapter ((VerticalRecyclerView) findViewById(R.id.vrv)).setAdapter(rvAdapter); //设置监听器 setOnCYGlobalLayoutListener(view_keybord, new OnCYGlobalLayoutListener() { //键盘刚显示 @Override public void onKeyboardShowedNow(Rect rect) { } //键盘刚隐藏,可以对输入的内容进行修改 @Override public void onKeyboardHideNow() { } //假键盘高度 @Override public int getViewKeyboardHeight(Rect rect) { return screenHight-rect.bottom;//screenHight-rect.bottom就是键盘高度 } }); } } 源码: /** * Created by cy on 2018/9/6.,用在普通界面中的edittext */ public abstract class KeyboardActivity extends AppCompatActivity implements ViewTreeObserver.OnGlobalLayoutListener { public int screenHight = 0; private OnCYGlobalLayoutListener onCYGlobalLayoutListener; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); screenHight = ScreenUtils.getScreenHeight(getApplicationContext()); } @Override protected void onResume() { super.onResume(); addGlobal(); } @Override protected void onStop() { super.onStop(); removeGlobal(); } private void addGlobal() { if (onCYGlobalLayoutListener!=null) getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(this); } private void removeGlobal() { getWindow().getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(this); } @Override public void onGlobalLayout() { // CYLogUtils.log("布局变化", "---------------------------------------"); Rect r = new Rect(); //获取当前界面可视部分 getWindow().getDecorView().getWindowVisibleDisplayFrame(r); //如果屏幕高度和Window可见区域高度差值大于整个屏幕高度的1/3,则表示软键盘显示中,否则软键盘为隐藏状态。 // int heightDifference = screenHeight - (r.bottom - r.top); boolean isKeyboardShowing = r.bottom < ScreenUtils.getScreenHeight(getApplicationContext()); if (isKeyboardShowing) { // Toast.makeText(this, "键盘显示", Toast.LENGTH_SHORT).show(); removeGlobal(); onCYGlobalLayoutListener.onKeyboardShowedNow(r); //会导致布局不断刷新,无限制回调当前方法,所以做延迟回调处理 new Handler().postDelayed(new Runnable() { @Override public void run() { addGlobal(); } }, 100); } else { // Toast.makeText(this, "键盘隐藏", Toast.LENGTH_SHORT).show(); removeGlobal(); onCYGlobalLayoutListener.onKeyboardHideNow(); //会导致布局不断刷新,无限制回调当前方法,所以做延迟回调处理 new Handler().postDelayed(new Runnable() { @Override public void run() { addGlobal(); } }, 100); } } public int getScreenHight() { return screenHight; } /** * @param onCYGlobalLayoutListener */ public void setOnCYGlobalLayoutListener( OnCYGlobalLayoutListener onCYGlobalLayoutListener) { this.onCYGlobalLayoutListener = onCYGlobalLayoutListener; addGlobal(); } public interface OnCYGlobalLayoutListener { public void onKeyboardShowedNow(Rect rect);//键盘刚显示 public void onKeyboardHideNow();//键盘刚隐藏 } } /** * Created by cy on 2018/9/6.,假键盘,用在列表中的edittext */ public abstract class KeyboardMockActivity extends AppCompatActivity implements ViewTreeObserver.OnGlobalLayoutListener { private View view_keyboard; public int screenHight = 0; private OnCYGlobalLayoutListener onCYGlobalLayoutListener; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); screenHight = ScreenUtils.getScreenHeight(getApplicationContext()); } @Override protected void onResume() { super.onResume(); addGlobal(); } @Override protected void onStop() { super.onStop(); removeGlobal(); } private void addGlobal() { if (view_keyboard == null) return; getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(this); } private void removeGlobal() { getWindow().getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(this); } @Override public void onGlobalLayout() { if (view_keyboard == null) { removeGlobal(); return; } // CYLogUtils.log("布局变化", "---------------------------------------"); Rect r = new Rect(); //获取当前界面可视部分 getWindow().getDecorView().getWindowVisibleDisplayFrame(r); //如果屏幕高度和Window可见区域高度差值大于整个屏幕高度的1/3,则表示软键盘显示中,否则软键盘为隐藏状态。 // int heightDifference = screenHeight - (r.bottom - r.top); boolean isKeyboardShowing = r.bottom < ScreenUtils.getScreenHeight(getApplicationContext()); if (isKeyboardShowing) { if (view_keyboard.getVisibility() == View.VISIBLE) return; // Toast.makeText(this, "键盘显示", Toast.LENGTH_SHORT).show(); removeGlobal(); LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) view_keyboard.getLayoutParams(); layoutParams.height = onCYGlobalLayoutListener.getViewKeyboardHeight(r); view_keyboard.setVisibility(View.VISIBLE); onCYGlobalLayoutListener.onKeyboardShowedNow(r); //会导致布局不断刷新,无限制回调当前方法,所以做延迟回调处理 new Handler().postDelayed(new Runnable() { @Override public void run() { addGlobal(); } }, 100); } else { // Toast.makeText(this, "键盘隐藏", Toast.LENGTH_SHORT).show(); if (view_keyboard.getVisibility() == View.GONE) return; removeGlobal(); view_keyboard.setVisibility(View.GONE); onCYGlobalLayoutListener.onKeyboardHideNow(); //会导致布局不断刷新,无限制回调当前方法,所以做延迟回调处理 new Handler().postDelayed(new Runnable() { @Override public void run() { addGlobal(); } }, 100); } } public int getScreenHight() { return screenHight; } /** * @param view_keyboard 假键盘布局,使用时必须自行设置其高度,以满足 需要 * @param onCYGlobalLayoutListener */ public void setOnCYGlobalLayoutListener(View view_keyboard, OnCYGlobalLayoutListener onCYGlobalLayoutListener) { this.view_keyboard = view_keyboard; this.onCYGlobalLayoutListener = onCYGlobalLayoutListener; addGlobal(); } public interface OnCYGlobalLayoutListener { public void onKeyboardShowedNow(Rect rect);//键盘刚显示 public void onKeyboardHideNow();//键盘刚隐藏 public int getViewKeyboardHeight(Rect rect);//返回假键盘的高度,rect 可视区域 } } GitHub 关注专题Android开发常用开源库简书 微信公众号 QQ群

资源下载

更多资源
Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册