Android 日常问题解决

787 阅读5分钟

萌新如果有遇到以下bug可以尝试如下解放:

NestedScrollView嵌套RecyclerView时自动滚动一段距离,顶部显示不全

外层布局添加如下代码:

 android:focusable="true"//关键
 android:focusableInTouchMode="true"//关键
NestedScrollView嵌套RecyclerView滑动冲突

RecyclerView添加如下代码:

android:nestedScrollingEnabled="false"
viewpager+frgment 重置导航重新setAdapter 对应的fragment内容显示

setAdapter时调用下面方法: 这个方法大致意思就是清空Fragment缓存

 public void clearFrg() {
        if (vp.getAdapter() != null) {
            //获取FragmentManager实现类的class对象,这里指的就是FragmentManagerImpl
            Class<? extends FragmentManager> aClass = getChildFragmentManager().getClass();
            try {
                //1.获取其mAdded字段
                Field f = aClass.getDeclaredField("mAdded");
                f.setAccessible(true);
                //强转成ArrayList
                ArrayList<Fragment> list = (ArrayList) f.get(getChildFragmentManager());
                //清空缓存
                list.clear();

                //2.获取mActive字段
                f = aClass.getDeclaredField("mActive");
                f.setAccessible(true);
                //强转成SparseArray
                SparseArray<Fragment> array = (SparseArray) f.get(getChildFragmentManager());
                //清空缓存
                array.clear();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
Android 剪切板内容获取不到或者第一次获取不到问题
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        //延时一秒后再获取
        Handler().postDelayed({
            run {
                var content = get_copy()
            }
        }, 1000)
    }
    
 fun get_copy():String{

        var content = "";
        try {
            var clipboard = this.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
            var clipData = clipboard.primaryClip;
            var item = clipData?.getItemAt(0);
            content = item?.text.toString();
        } catch (e: Exception) {
        }
        return content
    } 
    
    
RecyclerView嵌套RecyclerView问题

滑动卡顿>尝试添加如下代码:

recyclerview.setItemViewCacheSize(200)
recyclerview.setHasFixedSize(true)
..
..
//子recyclerview 要关闭滑动
recyclerviewChild.isNestedScrollingEnabled = false

/**Set the number of offscreen views to retain before adding them to the potentially shared recycled view pool.
The offscreen view cache stays aware of changes in the attached adapter, allowing a LayoutManager to reuse those views unmodified without needing to return to the adapter to rebind them.
Params:
size – Number of views to cache offscreen before returning them to the general recycled view pool
**/

# 设置缓存大小
recyclerview.setItemViewCacheSize(200)

/**RecyclerView can perform several optimizations if it can know in advance that RecyclerView's size is not affected by the adapter contents. RecyclerView can still change its size based on other factors (e.g. its parent's size) but this size calculation cannot depend on the size of its children or contents of its adapter (except the number of items in the adapter).
If your use of RecyclerView falls into this category, set this to true. It will allow RecyclerView to avoid invalidating the whole layout when its adapter contents change.
Params:
hasFixedSize – true if adapter changes cannot affect the size of the RecyclerView.
**/


//如果 RecyclerView 提前知道 RecyclerView 的大小不受适配器内容的影响,增加该属性能够提高效率
recyclerview.setHasFixedSize(true)

刷新数据优化:

//当前最后一条数据索引
var index = list.size
//page:当前分页数
if (page == 1) {
    list.clear()
    list.addAll(mList)
} else {
    list.addAll(mList)
}
if (page==1){
     mAdapter.notifyDataSetChanged()
}else{
    //加载分页从最后一条数据索引处加入
     mAdapter.notifyItemRangeInserted(index,list.size-1)
}

删除数据优化:

if (index_delete==-1||index_delete>=list.size){
    return
}
list.removeAt(index_delete)
mAdapter.notifyItemRemoved(index_delete)
//刷新被删除数据,以及其后面的数据
mAdapter.notifyItemRangeChanged(index_delete,mAdapter.itemCount) 

刷新一条数据优化-> 以点击关注举例:

//mAdapter.notifyItemChanged(index) 用下面带两个参数的 第二个参数随意命名
mAdapter.notifyItemChanged(index,"attention")

//```RecyclerView.Adapter 重写下面带三个参数onBindViewHolder()中刷新数据 *正常数据加载还是在两个参数onBindViewHolder()中
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int, payloads: MutableList<Any>) {

    if (payloads.isEmpty()){
        super.onBindViewHolder(holder, position, payloads)
    }else{
     //这里处理item需要更新的控件 
        if (holder is fGoldViewHolder) {
         
            with(holder) {
                with(mBinding) {
                    var map = list[position]  
                    if (map_user["is_follow"] == "1") {
                        imgvAtten.setImageResource(R.mipmap.ic_66)
                    } else {
                        imgvAtten.setImageResource(R.mipmap.ic_10)
                    }
                }
            }
        }
    }
}
Activity+Fragment+ViewPager2+Fragment刷新Fragment数据

嵌套结构:Activity+HomeFrg+ViewPager2+HomeListFrg 在Activity中刷新HomeListFrg中的RecyclerView数据

Activity:

//Activity通过findFragmentByTag获取的HomeFrg
var frg = supportFragmentManager.findFragmentByTag(HomeFrg::class.java.toString())
if (frg is HomeFrg) {
    frg.refreshData()
}

HomeFrg:


var list_frg =  ArrayList<HomeListFrg>()

list_frg.add(HomeListFrg.create("mine_addention"))
list_frg.add(HomeListFrg.create("mine_recommend"))
list_frg.add(HomeListFrg.create("mine_new"))

viewPager.adapter = HomeListAdataper(childFragmentManager, this@HomeFrg.lifecycle, list_frg)

//获取到viewPager2当前选中项
fun refreshData() {
    var index = mBinding.viewPager.currentItem
    var frg = list_frg[index]
    frg.refreshData()
}

HomeListFrg:

 fun refreshData(){
   //刷新RecyclerView
    mBinding.swipeRefreshLayout.startRefresh()
 }
防止重复点击

添加如下代码:

public class MyUtils {

    // 两次点击按钮之间的点击间隔不能少于1000毫秒
    private static final int MIN_CLICK_DELAY_TIME = 1000;
    private static long lastClickTime;

    public static boolean isFastClick() {
        boolean flag = false;
        long curClickTime = System.currentTimeMillis();
        if ((curClickTime - lastClickTime) >= MIN_CLICK_DELAY_TIME) {
            flag = true;
        }
        lastClickTime = curClickTime;
        return flag;
    }

需要防止重复点击添加如下代码:

imgvPost.setOnClickListener {
    if (!MyUtils3.isFastClick()){
        return@setOnClickListener
    }
    ..
    ..
}

或者:

fun mainClick(v: View) {
    if (!MyUtils3.isFastClick()&&v.id!=R.id.tv01){
        return
    }
    when(v.id){
    
      //按钮tv01不添加防止重复处理
       R.id.tv01->{
       
       }
       
       R.id.tv02->{
       
       }
       ..
       ..
       
    }
}

Android studio mac环境连接夜神模拟器

1.夜神模拟器Nox APP Player Mac版 下载地址www.pc6.com/mac/338210.…

2.mac 环境变量配置

  1. 打开终端,输入: cd ~/进入用户目录;\
  2. 输入:touch .bash_profile,如果当前没有这个文件,则会默认创建;\
  3. 输入:open .bash_profile,如果是第一次创建,则默认为空白的文件;

bash_profile文件输入:

export ANDROID_HOME=/Users/work/Library/Android/sdk
export PATH=${PATH}:${ANDROID_HOME}/tools
export PATH=${PATH}:${ANDROID_HOME}/platform-tools

输入source .bash_profile即可使改动生效; 重启studio即生效

3.连接夜神模拟器 studio控制台输入 adb connect 127.0.0.1:62001

全局Tost, 自定义view Toast, 生命周期Toast

//动态设置控件尺寸 包括字体大小达到适配效果

特别说明:此处 AutoUtils.getPercentWidthSizeBigger(int)是根据屏幕宽度 动态获取的尺寸 为了达到适配效果 如果不需要适配自行替换成dp

public class ToastUitl {

    private static Toast toast;

    public static void showShort(Context context, CharSequence str) {
        showToast(context,str,Toast.LENGTH_SHORT);
    }

    public static void showLong(Context context, CharSequence str) {
        showToast(context,str,Toast.LENGTH_LONG);
    }

    public static void showToast(Context context, CharSequence text, int duration) {
        if (toast == null) {
            toast =  new Toast(context);
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View layout = inflater.inflate(R.layout.toast_img, null);
            TextView textView = (TextView) layout.findViewById(R.id.tv_content);
            RelativeLayout relay_bg = (RelativeLayout) layout.findViewById(R.id.relay_bg);
            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) relay_bg.getLayoutParams();
            layoutParams.height = AutoUtils.getPercentWidthSizeBigger(360);
            layoutParams.width = AutoUtils.getPercentWidthSizeBigger(360);
            int paddings =  AutoUtils.getPercentWidthSizeBigger(20);
            relay_bg.setPadding(paddings,paddings,paddings,paddings);
            relay_bg.setLayoutParams(layoutParams);
            textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, AutoUtils.getPercentWidthSizeBigger(42));
            textView.setText(text);
            toast.setView(layout);
            toast.setGravity(Gravity.CENTER | Gravity.TOP, 0, AutoUtils.getPercentHeightSize(650));
            toast.setDuration(duration);
        }else{
            View  v =toast.getView();
            TextView textView =v.findViewById(R.id.tv_content);
            textView.setText(text);
        }
        toast.show();
    }

    public static void destroy(){
        if (toast!=null){
            toast.cancel();
        }
    }
}
public static int getPercentWidthSizeBigger(int val)
{
    //当前屏幕宽度
    int screenWidth = AutoLayoutConifg.getInstance().getScreenWidth();
    //设计宽度(这个数值根据需求自行定义哈 一般定义为1080)
    int designWidth = AutoLayoutConifg.getInstance().getDesignWidth();

    int res = val * screenWidth;
    if (res % designWidth == 0)
    {
        return res / designWidth;
    } else
    {
        return res / designWidth + 1;
    }

}

xml代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:id="@+id/relay_bg"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@drawable/shape_toast"
       >

        <TextView
            android:id="@+id/tv_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:gravity="center"
            android:text=""
            android:ellipsize="end"
            android:textColor="#FFFFFFFF"
            android:textSize="42px" />

    </RelativeLayout>


</RelativeLayout>

防止页面销毁吐司不断弹出

生命周期处理: activity失去焦点 吐丝不会在显示

//这样处理 activity失去焦点 吐丝不会在显示
override fun onPause() {
    super.onPause()
    ToastUitl.destroy()
}
全局用户信息简单处理
open class BaseApp() : Application() {

    var map_info = HashMap<String, String>()

    companion object {

        var instance: BaseApp? = null

        fun getInstanceApp(): BaseApp? {
            return instance
        }
    }

    fun getOneMapData(key: String): String {
        var value = ""
        if (map_info.containsKey(key)) {
            value = map_info[key]!!
        } else {
            //application 获取不到 从sp中获取 
            value =PreferencesUtils.getString(context,key,"")
            map_info[key]=value
        }
        return value
    }

    fun saveOneMapData(key:String,value: String){
        map_info[key]=value
        PreferencesUtils.putString(context,key,value)

    }

    override fun onCreate() {
        super.onCreate()
        instance = this
    }
 }
Could not initialize class com.android.sdklib.repository.AndroidSdkHandler
gradle版本太老 更新一下
.gitignore修改后 studio提交代码不生效

切换到当前目录清理下git缓存

git rm -r --cached .