美文网首页
日常备忘录

日常备忘录

作者: 间歇性丶神经病患者 | 来源:发表于2017-12-11 15:55 被阅读37次

    [toc]

    adb

    1. 权限禁止
    su root 
    
    1. 查看xml文件
    cat  data.xml
    
    1. 权限禁止的情况下进入包目录
    run-as com.your.package  
    

    webView图片显示不全

     webSettings.setJavaScriptEnabled(true); // 设置支持javascript脚本
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
                webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
            }
            webSettings.setBlockNetworkImage(false);
    

    Pw在7.0或以上显示showAsDropDown有问题

    public void showAsDropDown(View anchor) {
        if (Build.VERSION.SDK_INT >= 24) {// 只有7.0 的系统有这个问题
            int[] location = new int[2];
            anchor.getLocationOnScreen(location);
            int x = location[0];
            int y = location[1];
            showAtLocation(anchor, Gravity.NO_GRAVITY, 0, y + anchor.getHeight());
        } else {
            super.showAsDropDown(anchor);
        }
    }
    

    ApplicationContext以及ActivityContext区别

    image.png

    Retrofit 备忘录

    1. 添加拦截器添加公共头
     private fun client(): OkHttpClient {
            if (TextUtils.isEmpty(url)) {
                throw IllegalArgumentException("baseUrl can not be null")
            }
            val builder = OkHttpClient.Builder()
            builder.connectTimeout(connectTimeoutMills, TimeUnit.MILLISECONDS)
            builder.readTimeout(readTimeoutMills, TimeUnit.MILLISECONDS)
            builder.addInterceptor { chain ->
              val request = chain.request()?.newBuilder()?.addHeader("showapi_appid", NetConf.showApiAppId)
                       ?.addHeader("showapi_sign", NetConf.showApiSign)!!.build()
                chain.proceed(request)
            }
            return builder.build()
        }
    

    2.添加拦截器添加公共参数

     private fun client(): OkHttpClient {
            if (TextUtils.isEmpty(url)) {
                throw IllegalArgumentException("baseUrl can not be null")
            }
            val builder = OkHttpClient.Builder()
            builder.connectTimeout(connectTimeoutMills, TimeUnit.MILLISECONDS)
            builder.readTimeout(readTimeoutMills, TimeUnit.MILLISECONDS)
            builder.addInterceptor { chain ->
                val httpUrl = chain.request().url().newBuilder().addQueryParameter("showapi_appid", NetConf.showApiAppId)
                        .addQueryParameter("showapi_sign", NetConf.showApiSign).build()
                val request = chain.request().newBuilder().url(httpUrl).build()
                chain.proceed(request)
            }
            return builder.build()
        }
    

    知识点备忘录

    android架构

    Activity生命周期

    image.png

    Fragment生命周期

    image.png

    RxJava

    image.png

    部分命名规则

    名称 缩写
    Button btn
    CheckBox cb
    EditText et
    FrameLayout fl
    GridView gv
    ImageButton ib
    ImageView iv
    LinearLayout ll
    ListView lv
    ProgressBar pb
    RadioButtion rb
    RecyclerView rv
    RelativeLayout rl
    ScrollView sv
    SeekBar sb
    Spinner spn
    TextView tv
    ToggleButton tb
    VideoView vv
    WebView wv

    kotlin中还没理解透彻的点:

    内部类的作用(好处):

    讲解

    image.png

    线程问题:

    sleep和wait的区别

    1. Sleep是Thread的方法,wait是Object类的方法
    2. Thread.sleep不会导致锁行为的改变,如果当前线程是拥有锁的,那么Thread.sleep不会让线程释放锁
    3. Thread.sleep和Object.wait都会暂停当前的线程,对于CPU资源来说,不管是哪种方式暂停的线程,都表示它暂时不再需要CPU的执行时间,但是wait需要别的线程执行notify/notifyAll才能够重新获得CPU执行时间
    image.png

    线程间的状态转换:

    1. 新建(new):新创建了一个线程对象。

    2. 可运行(runnable):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。

    3. 运行(running):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。

    4. 阻塞(block):阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种:

    • 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。

    • 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。

    • 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。

    1. 死亡(dead):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。

    总结:

    1. sleep方法调用之后,并没有释放锁。使得线程仍然可以同步控制。sleep不会让出系统资源;wait是进入线程等待池中等待,让出系统资源
    2. 调用wait方法的线程,不会自己唤醒,需要线程调用 notify / notifyAll 方法唤醒等待池中的所有线程,才会进入就绪队列中等待系统分配资源。sleep方法会自动唤醒,如果时间不到,想要唤醒,可以使用interrupt方法强行打断
    3. Thread.sleep(0) // 触发操作系统立刻重新进行一次CPU竞争。
    4. sleep可以在任何地方使用。而wait,notify,notifyAll只能在同步控制方法或者同步控制块中使用。
    5. sleep必须捕获异常,而wait,notify,notifyAll的不需要捕获异常。

    数据结构

    HashMap和Hashtable的区别?

    1. 两者最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全
    2. HashMap可以使用null作为key,而Hashtable则不允许null作为key
    3. 两者计算hash的方法不同
      • Hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模
      • HashMap计算hash对key的hashcode进行了二次hash,以获得更好的散列值,然后对table数组长度取摸
    4. HashMap和Hashtable的底层实现都是数组+链表结构实现

    Hanler Looper Message

    Looper主要作用:

    1. 与当前线程绑定,保证一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue。
    2. loop()方法,不断从MessageQueue中去取消息,交给消息的target属性的dispatchMessage去处理。

    总结:

    1. 首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
    2. Looper.loop()会让当前线程进入一个无限循环,不断从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
    3. Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue相关联。
    4. Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
    5. 在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。

    Context 以及ApplicationContext 使用场景

    image.png

    大家注意看到有一些NO上添加了一些数字,其实这些从能力上来说是YES,但是为什么说是NO呢?下面一个一个解释:

    数字1:启动Activity在这些类中是可以的,但是需要创建一个新的task。一般情况不推荐。

    数字2:在这些类中去layout inflate是合法的,但是会使用系统默认的主题样式,如果你自定义了某些样式可能不会被使用。

    数字3:在receiver为null时允许,在4.2或以上的版本中,用于获取黏性广播的当前值。(可以无视)

    注:ContentProvider、BroadcastReceiver之所以在上述表格中,是因为在其内部方法中都有一个context用于使用。

    布局优化

    1. include
    2. merge
    3. viewStub(不可以与merge同时使用,会增加绘制层数,如何取舍看具体业务)

    include

    • 优点:可以引入重复内容,避免xml重复 复制黏贴
    • 缺点:可能会引入额外的布局嵌套

    merge

    • 优点:是include的辅助补充,可以避免xml布局嵌套
    • 缺点:不会引用引入额外的布局嵌套

    viewStub
    仅在需要时才加载布局

    • 优点:仅在需要的时候才会引入布局,可以防止View.GONE导致的性能损耗
    • 缺点:比较麻烦(个人觉得)
    • 使用方法:
      • xml 中使用:
      • java代码中使用:
            <ViewStub   
                android:id="@+id/view_stub"  
                android:layout="@layout/profile_extra"  
                android:layout_width="match_parent"  
                android:layout_height="wrap_content"  
                />  
    
        ViewStub viewStub = (ViewStub) findViewById(R.id.view_stub);  
        if (viewStub != null) {  
            View inflatedView = viewStub.inflate();  
            editExtra1 = (EditText) inflatedView.findViewById(R.id.edit_extra1);  
            editExtra2 = (EditText) inflatedView.findViewById(R.id.edit_extra2);  
            editExtra3 = (EditText) inflatedView.findViewById(R.id.edit_extra3);  
        }  
    

    Dalvik和ART的区别?

    Dalvik与JVM的区别

    1. Dalvik指令集是基于寄存器的架构,dex字节码更适合于内存和处理器速度有限的系统。
    2. 而JVM是基于栈的。相对而言,基于寄存器的Dalvik实现虽然牺牲了一些平台无关性,但是它在代码的执行效率上要更胜一筹。
    3. Dalvik 是Android4.4及以下平台的虚拟机。Art 是在Android4.4以上平台使用的虚拟机。

    ART的优点:

    1. ART 性能高于采用JIT的Dalvik
    2. 应用启动更快、运行更快、体验更流畅、触感反馈更及时
    3. 更长的电池续航能力
    4. 支持更低的硬件

    ART的缺点:

    1. 字节码变为机器码之后,占用的存储空间更大
    2. 应用的安装时间会变长。

    堆内存和栈内存的区别

    1、应用程序所有的部分都使用堆内存,然后栈内存通过一个线程运行来使用。

    2、不论对象什么时候创建,他都会存储在堆内存中,栈内存包含它的引用。栈内存只包含原始值变量好和堆中对象变量的引用。

    3、存储在堆中的对象是全局可以被访问的,然而栈内存不能被其他线程所访问。

    4、栈中的内存管理使用LIFO的方式完成,而堆内存的管理要更复杂了,因为它是全局被访问的。堆内存被分为,年轻一代,老一代等等,更多的细节请看,这篇文章

    5、栈内存是生命周期很短的,然而堆内存的生命周期从程序的运行开始到运行结束。

    6、我们可以使用-Xms和-Xmx JVM选项定义开始的大小和堆内存的最大值,我们可以使用-Xss定义栈的大小

    7、当栈内存满的时候,Java抛出java.lang.StackOverFlowError异常而堆内存满的时候抛出java.lang.OutOfMemoryError: Java Heap Space错误

    8、和堆内存比,栈内存要小的多,因为明确使用了内存分配规则(LIFO),和堆内存相比栈内存非常快。

    HttpClient与HttpUrlConnection的区别

    • android 2.3 之前推荐用HttpClient,因为HttpUrlConnection存在较多的、莫名其妙的bug
    • android 2.3 以后推荐用HttpUrlConnection,因为更方便,更快捷。
      比如Volley
      讲解

    http与https的区别:

    1. HTTP 的 URL 以 http:// 开头,而 HTTPS 的 URL 以 https:// 开头
    2. HTTP 是不安全的,而 HTTPS 是安全的
    3. HTTP 标准端口是 80 ,而 HTTPS 的标准端口是 443
    4. 在 OSI 网络模型中,HTTP 工作于应用层,而 HTTPS 工作在传输层
    5. HTTP 无需加密,而 HTTPS 对传输的数据进行加密
    6. HTTP 无需证书,而 HTTPS 需要认证证书
      讲解

    Activity的启动过程:

    讲得很好的一篇文章

    单例模式

    单例模式

    日常bug

    1. ViewPager 配合PhotoView 在快递缩放的情况下会报错


      image.png

      这个时候需要自定义ViewPager

    /**
     * @author Ly
     * @date 2017/12/11
     */
    
    public class PhotoViewPager extends ViewPager {
        public PhotoViewPager(Context context) {
            super(context);
        }
    
        public PhotoViewPager(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            try {
                return super.onInterceptTouchEvent(ev);
            } catch (Exception e) {
                // ignore it
            }
            return false;
        }
    
    
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            try {
                return super.onTouchEvent(ev);
            } catch (IllegalArgumentException ex) {
                // ignore it
            }
            return false;
        }
    }
    
    
    1. ViewPager 图片刷新,适配器用的是FragmentStatePagerAdapter,其实应该用FragmentPagerAdapter性能更好。
    /**
     * @author Ly
     * @date 2017/12/26
     */
    
    public class BigImageAdapter extends FragmentStatePagerAdapter {
    
        private ArrayList<Fragment> mFragmentList;
    
        public BigImageAdapter(FragmentManager fm, List<String> types) {
            super(fm);
            updateData(types);
        }
    
        public void updateData(List<String> dataList) {
            ArrayList<Fragment> fragments = new ArrayList<>();
            for (int i = 0, size = dataList.size(); i < size; i++) {
                fragments.add(BigImageFragment.newInstance(dataList.get(i)));
            }
            setFragmentList(fragments);
        }
    
        private void setFragmentList(ArrayList<Fragment> fragmentList) {
            if (this.mFragmentList != null) {
                mFragmentList.clear();
            }
            this.mFragmentList = fragmentList;
            notifyDataSetChanged();
        }
    
        @Override
        public int getCount() {
            return this.mFragmentList.size();
        }
    
        @Override
        public int getItemPosition(Object object) {
            return POSITION_NONE;
        }
    
        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }
    }
    
    1. EditText 字符输入限制
      例如我的游戏区服 只能输入0-300,那么就是:
     mEtRepurchaseServed.setFilters(new InputFilter[]{new MaxNumFilter(0, 300, 2)});
    
    /**
     * @author Ly
     *         最大输入字符限制
     *         <p>
     *         <p>
     *         eg:
     *         mEtRepurchaseServed.setFilters(new InputFilter[]{new MaxNumFilter(0, 300, 2)});
     *         mEtRepurchaseLevel.setFilters(new InputFilter[]{new MaxNumFilter(0, 65535, 2)});
     * @date 2017/12/25
     */
    
    public class MaxNumFilter implements InputFilter {
        private final Pattern pattern;
        private final double maxNum;
    
    
        public MaxNumFilter(int min, double maxNum, int numOfDecimals) {
            pattern = Pattern.compile("^" + (min < 0 ? "-?" : "")
                    + "[0-9]*\\.?[0-9]" + (numOfDecimals > 0 ? ("{0," + numOfDecimals + "}$") : "*"));
            this.maxNum = maxNum;
        }
    
        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            if (source.equals(".")) {
                if (dstart == 0 || !(dest.charAt(dstart - 1) >= '0' && dest.charAt(dstart - 1) <= '9') || dest.charAt(0) == '0') {
                    return "";
                }
            }
            if (source.equals("0") && (dest.toString()).contains(".") && dstart == 0) {
                return "";
            }
    
            StringBuilder builder = new StringBuilder(dest);
            builder.delete(dstart, dend);
            builder.insert(dstart, source);
            if (!pattern.matcher(builder.toString()).matches()) {
                return "";
            }
    
            if (!TextUtils.isEmpty(builder)) {
                double num = Double.parseDouble(builder.toString());
                if (num > maxNum) {
                    return "";
                }
            }
            return source;
        }
    }
    
    1. RecyclerView 嵌套RecyclerView 出现滑动冲突
      场景:
      RecyclerView嵌套了RecyclerView,当手指滑动子RecyclerView的时候,滑动焦点处于子RecyclerView,父RecyclerView滑动不了。 S80125-11003805[1].jpg

    这个时候,我们父RecyclerView不用做处理,子RecyclerView做如下处理:

                val discountList = arrayListOf<DiscountBean>()
                for (i in 0..1) {
                    discountList.add(DiscountBean(i, i.toString(), i.toString()))
                }
                val discountAdapter = DiscountAdapter(discountList, context)
                mRlvProductDiscount?.layoutManager = LinearLayoutManager(context)
                mRlvProductDiscount?.adapter = discountAdapter
                mRlvProductDiscount?.isNestedScrollingEnabled=false
    

    主要是这句:

     mRlvProductDiscount?.isNestedScrollingEnabled=false
    

    禁止了该mRlvProductDiscount的滑动事件

    redis 启动失败:

    window下安装redis报错:
    creating server tcp listening socket 127.0.0.1:6379: bind No error

    的解决方案如下按顺序输入如下命令就可以连接成功

    
    1. redis-cli.exe
    2. shutdown
    3. exit
    4. redis-server.exe redis.windows.conf
    

    相关文章

      网友评论

          本文标题:日常备忘录

          本文链接:https://www.haomeiwen.com/subject/gdgiixtx.html