走进Java Android 的线程世界

走进源码pipe、epoll,Android面试最常见Handler、Looper、Message问题总结与解答 【转载请注明出处:走进源码,Android面试最常见Handler、Looper、Message问题总结与解答优快云王智博】 今天楼主以面试的角度,走进源码,去探索Handler、Handler、Looper、Message的奥秘。 随着各种网络框架的普及,线程之间的通信再也不需要我们手动的创建Handler,然后handleMessage了,但是当我们想要创建一个主线程延时任务的时候,... 阅读详情

直奔主题

首先我们来看看Java的线程通讯基础


    //产品
    static class ProductObject{
        //线程操作变量可见
        public volatile static String value;
    }

    //生产者线程
    static class Producer extends Thread{
        Object lock;

        public Producer(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            //不断生产产品
            while(true){
                synchronized (lock) { //互斥锁
                    //产品还没有被消费,等待
                    if(ProductObject.value != null){
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    //产品已经消费完成,生产新的产品
                    ProductObject.value = "NO:"+System.currentTimeMillis();
                    Log.i(TAG,"生产产品:"+ProductObject.value);
                    lock.notify(); //生产完成,通知消费者消费
                }
            }

        }
    }

    //消费者线程
    static class Consumer extends Thread{
        Object lock;
        public Consumer(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            while(true){
                synchronized (lock) {
                    //没有产品可以消费
                    if(ProductObject.value == null){
                        //等待,阻塞
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    Log.i(TAG,"消费产品:"+ProductObject.value);
                    ProductObject.value = null;
                    lock.notify(); //消费完成,通知生产者,继续生产
                }
            }
        }
    }

调用:

        Object lock = new Object();
        new Producer(lock).start();
        new Consumer(lock).start();

Log:
这里写图片描述

这是一些简单的线程通讯基础,两个线程进行交互的用法。

接下来分析一下 Java中的FutureTask

我们先来看看类图
这里写图片描述
再看看怎么用的

    //异步任务
    static class Task implements Callable<Integer> {
        //返回异步任务的执行结果
        @Override
        public Integer call() throws Exception {
            int i = 0;
            for (; i < 10; i++) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Log.i(TAG, Thread.currentThread().getName() + "_" + i);
            }
            return i;
        }
    }

初始化执行

        Task work = new Task();
        FutureTask<Integer> future = new FutureTask<Integer>(work) {
            //异步任务执行完成,回调
            @Override
            protected void done() {
                try {
                    Log.i(TAG, "done:" + get());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
        };
        //线程池(使用了预定义的配置)
        ExecutorService executor = Executors.newCachedThreadPool();
        executor.execute(future);

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        //取消异步任务
//        future.cancel(true);
        try {
            //阻塞,等待异步任务执行完毕
            Log.i(TAG, "" + future.get());

        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

Log:
这里写图片描述
从上面代码可以看出
这个FutureTask 解决异步任务执行的结果,主线程无法轻易的获取
这是怎么做到的呢–>我们就需要翻越FutureTask的代码

Future

package java.util.concurrent;

public interface Future<V> {

    boolean cancel(boolean mayInterruptIfRunning);

    boolean isCancelled();

    boolean isDone();

    V get() throws InterruptedException, ExecutionException;

    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

Runnable

package java.lang;

public interface Runnable {
    public abstract void run();
}

RunnableFuture

package java.util.concurrent;

public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run();
}

FutureTask


package java.util.concurrent;

import java.util.concurrent.locks.LockSupport;

public class FutureTask<V> implements RunnableFuture<V> {
    ......以下只截取部分代码
    /** The underlying callable; nulled out after running */
    private Callable<V> callable;

    /** The thread running the callable; CASed during run() */
    private volatile Thread runner;

    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

    public boolean cancel(boolean mayInterruptIfRunning) {
        if (!(state == NEW &&
              U.compareAndSwapInt(this, STATE, NEW,
                  mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
            return false;
        try {    // in case call to interrupt throws exception
            if (mayInterruptIfRunning) {
                try {
                    Thread t = runner;
                    if (t != null)
                        t.interrupt();
                } finally { // final state
                    U.putOrderedInt(this, STATE, INTERRUPTED);
                }
            }
        } finally {
            finishCompletion();
        }
        return true;
    }

    /**
     * @throws CancellationException {@inheritDoc}
     */
    public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }




    protected void done() { }


    protected void set(V v) {
        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
            outcome = v;
            U.putOrderedInt(this, STATE, NORMAL); // final state
            finishCompletion();
        }
    }


    protected void setException(Throwable t) {
        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
            outcome = t;
            U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state
            finishCompletion();
        }
    }

    public void run() {
        if (state != NEW ||
            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }


    private void finishCompletion() {
        // assert state > COMPLETING;
        for (WaitNode q; (q = waiters) != null;) {
            if (U.compareAndSwapObject(this, WAITERS, q, null)) {
                for (;;) {
                    Thread t = q.thread;
                    if (t != null) {
                        q.thread = null;
                        LockSupport.unpark(t);
                    }
                    WaitNode next = q.next;
                    if (next == null)
                        break;
                    q.next = null; // unlink to help gc
                    q = next;
                }
                break;
            }
        }

        done();

        callable = null;        // to reduce footprint
    }
    ......以上只截取部分代码
}

从上面代码可以看出
Java FutureTask 异步任务操作提供了便利性
1.获取异步任务的返回值–> V get()
2.监听异步任务的执行完毕–>finishCompletion()–>done()
3.取消异步任务–>cancel(boolean mayInterruptIfRunning)

从上面的例子,我们可以看到Executors去调用这个Future那么这个Executors又是啥玩意呢?!

像刚才看Future那样我们点进去看看这个Executors我们可以发现很多东西,然而,其实这个就是鼎鼎大名的 线程池 !
我们还是先看看类图
这里写图片描述

因为实现类方法太多了,还是直接看api文档比较好。

一个任务

    static class MyTask implements Runnable {

        int i;

        public MyTask(int i) {
            this.i = i;
        }

        @Override
        public void run() {
            Log.i(TAG, Thread.currentThread().getName() + ";i:" + i);
        }

    }

初始化–>运行线程池

        int CPU_COUNT = Runtime.getRuntime().availableProcessors();  //可用的CPU个数
        Log.i(TAG, "CPU_COUNT-->" + CPU_COUNT);
        int CORE_POOL_SIZE = CPU_COUNT + 1; //5(corePoolSize - 池中所保存的线程数,包括空闲线程。)
        Log.i(TAG, "CORE_POOL_SIZE-->" + CORE_POOL_SIZE);
        int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; //9(maximumPoolSize - 池中允许的最大线程数。)
        Log.i(TAG, "MAXIMUM_POOL_SIZE-->" + MAXIMUM_POOL_SIZE);

        int KEEP_ALIVE = 1;//(keepAliveTime - 当线程数大于核心时,此为终止前多余的空闲线程等待新任务的最长时间。)

        //任务队列(128)(workQueue - 执行前用于保持任务的队列。此队列仅由保持 execute 方法提交的 Runnable 任务。)
        final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128);

        //线程工厂(threadFactory - 执行程序创建新线程时使用的工厂。)
        ThreadFactory sThreadFactory = new ThreadFactory() {
            private final AtomicInteger mCount = new AtomicInteger(1);

            public Thread newThread(Runnable r) {
                String name = "Thread #" + mCount.getAndIncrement();
                Log.i(TAG, "newThread-->" + name);
                return new Thread(r, name);
            }
        };

        //线程池
        Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                //(unit - keepAliveTime 参数的时间单位。)
                TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);


        /*  如果运行的线程少于 corePoolSize,则 Executor 始终首选添加新的线程,而不进行排队。
            如果运行的线程等于或多于 corePoolSize,则 Executor 始终首选将请求加入队列,而不添加新的线程。
            如果无法将请求加入队列,则创建新的线程,除非创建此线程超出 maximumPoolSize,在这种情况下,任务将被拒绝。*/
        //执行异步任务
        //如果当前线程池中的数量大于corePoolSize,缓冲队列workQueue已满,
        //并且线程池中的数量等于maximumPoolSize,新提交任务由Handler处理。
        //RejectedExecutionException
        for (int i = 0; i < 200; i++) {
            //相当于new AsyncTask().execute();
            THREAD_POOL_EXECUTOR.execute(new MyTask(i));
        }

Log如下
这里写图片描述
从Log我们可以看出每个任务都有一个线程去完成。

其实这个就是Android中AsyncTask的原理我们不妨分析一下AsyncTask:

初始化

这里写图片描述

执行

这里写图片描述

返回

这里写图片描述

返回UI线程

这里写图片描述

Progress更新UI

这里写图片描述

JAVA API 文档:http://tool.oschina.net/apidocs/apidoc?api=jdk-zh
Android API文档:http://tool.oschina.net/apidocs/apidoc?api=android/reference
文章代码:https://github.com/gepriniusce/TongsonPlay/tree/Threah

万字长文带你走进Android service(服务)的理解与实战 主要介绍了服务中的一些特性,比如服务的应用场景、服务的整体概述、服务的启动与销毁,并通过案例演示了服务的生命周期。下一篇文章将介绍服务的其他特性,如:前台服务、服务与其他组件的交互过程、发送通知及绑定服务等。再下一文章中介绍Android中的进程与线程,紧接着介绍binder机制与原理,逐渐深入。 阅读详情

相关推荐

Android(Java)线程的两种实现方式

Android(Java)线程的两种实现方式

Android 线程和线程池核心技术-走进线程世界 (一)

UI线程优先级为-10 , 线程的优先级具有竞争性 , 所以会和我们的子线程进行竞争。线程的优先级具有继承性 , 在某线程中创建的线程会继承此线程的优先级。那么我们在UI线程中创建了线程 , 则线程的优先级和UI线程的优先级一样 , 平等和UI线程抢占CPU时间片资源。, 限制了新设置的线程的优先级必须为[1~10] , 优先级priority的值越高 , 获取CPU时间片的概率越高。引用工作线程的原因 : UI线程都是用来更新UI控件的 , 耗时任务也在UI线程中来执行 , 势必会引起UI线程的。

我很好 899

Cocos Creator 3D音频定位实战:从原理到沉浸感实现

3D音频定位是游戏开发中实现沉浸感的关键技术,其核心原理基于HRTF(头部相关传输函数)模型,模拟声音在空间中的传播与双耳感知差异。这项技术通过赋予声音空间坐标、距离衰减和方向属性,将音频从背景元素提升为可交互的环境线索,极大增强了虚拟世界的真实感与玩家的空间认知。在工程实践中,开发者需要深入理解声源、听者、衰减曲线与多普勒效应等基础概念,并合理运用音频池、优先级管理与动态混音等技术手段来平衡效果与性能。对于Cocos Creator开发者而言,无论是使用引擎原生的AudioSource组件构建轻量级方案,

weixin_30972263的博客 294

Java/Android 进程与线程之 多线程开发(二)

多线程开发Java多线程开发1、线程状态线程阻塞线程协作作用**wait() / notify****join()****Thread.sleep()**wait 与 sleep 的区别与联系2、线程控制方法2.1 Synchronized定义原子性与可见性锁的升级内部机制**1. 对象头和monitor****2、偏向锁****3、轻量级锁(自旋锁)****4、重量级锁(互斥锁)**可重入锁 ()和 不可重入锁(自旋锁)类锁与对象锁2.2 volatile定义原理特性2.3 ReentrantLock定义

lizhichao628的专栏 501

智能农业大棚

目 录 摘要 1.绪论 2.系统概述及单片机介绍 2.1整体方案设计思想 2.2系统组成 2.2.1主控芯片的选择 2.2.2传感器模块选择 2.2.3电机驱动模块 2.3 单片机介绍 2.3.1 AT89C51单片机的基本组成 2.3.2AT89C51主要特性 2.3.3管脚说明 2.3.4 AT89C51单片机的存储器 2.3.4.1 程序存储器 2.3.4.2 数据存储器 2.3.5 振荡电路和时钟 2.3.6 AT89C51的中断

weixin_70886450的博客 1327

昇腾910B多卡环境下hccl-test性能调优实战

本文详细介绍了昇腾910B多卡环境下hccl-test性能调优的实战经验,包括环境搭建、CANN工具链配置、性能测试与高级调优技巧。通过优化缓冲区、PCIe拓扑和中断亲和性设置,显著提升多卡通信效率,为AI训练提供稳定高效的计算支持。

weixin_29216049的博客 848

java创建线程的三种方式及其对比

Java中创建线程主要有三种方式: 一、继承Thread类创建线程类 (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。 (2)创建Thread子类的实例,即创建了线程对象。 (3)调用线程对象的start()方法来启动该线程。 package com.thread; public class Firs

longshengguoji的专栏 18万+

SAP FICO 消息号 FAA_POST042 技术清算科目中的余额:分类账 0L,货币 00、RMB、10000.00-

SAP FICO 消息号 FAA_POST042 技术清算科目中的余额:分类账 0L,货币 00、RMB、10000.00-

我好像病了的博客 2139

android java 多线程,Android/Java 多线程分享

这篇博客主要有以下几点什么是线程,和进程的区别线程有哪几种状态线程安全的理解volatile关键字,是线程安全吗?为什么?和synchronize 的区别用过哪些锁?lock 和 synchronize 区别手写代码,线程1打印“A”,线程2打印“B”,按顺序输出“ABABABA...”1.什么是线程,和进程的区别要解释线程,就必须明白什么是进程。什么是进程呢?进程是指运行中的应用程序,每个进程都...

weixin_36328527的博客 267

第10章:位同步与Gardner环路(1)

第10章(1)内容如下:一、位同步与载波同步的区别1、采样时钟相位偏差的影响2、采样时钟频率偏差的影响二、Gardner环路算法与插值方法1、插值滤波器2、Gardner误差检查算法三、Gardner环路中环路滤波器与数字振荡器设计1、环路滤波器2、数控振荡器(NCO)四、Gardner环路的可运行MATLAB代码五、参考资料六、致谢 最近搞懂了Gardner环路的一些知识,于是更新第10章——位同步。 如果你稍不留意的话,这可能是你在网上能看到的介绍Gardner环路及其MATLAB仿真最详细的一篇文章了

weixin_44283855的博客 1万+

硅谷刷屏的ClawdBot,让Mac mini卖爆了!创始人爆料:一人开发、100% AI 写代码

这两天,个人 AI 助手 ClawdBot 席卷硅谷,国内外社交平台上全是关于它的讨论。 在试用后,网友们纷纷给出了很高的评价。“它是迄今为止最伟大的 AI 应用,相当于你 24 小时全天候专属 AI 员工。”Creator Buddy 创始人兼 CEO Alex Finn 盛赞道,“这就是他们 (Anthropic) 希望 Claude Cowork 呈现的样子。”

技术引领业务创新 1586

Android java创建子线程的几种方法

Android创建子线程的几种方法

976

模拟IC设计避坑:手把手教你用Cadence仿真恒定跨导轨到轨运放(附完整工艺库文件)

本文详细解析了使用Cadence仿真恒定跨导轨到轨运放的全流程,涵盖电路原理、工艺库配置、尺寸设计及仿真分析。通过1:3电流镜补偿技术实现跨导稳定,提供CSMC 0.25um工艺下的实战案例,帮助工程师规避设计陷阱,提升模拟IC设计效率。

weixin_30952535的博客 497

走进Java Android 的线程世界(二)线程池

上集回顾: 上集我们稍做讲解了Future与Executor Executors 创建并得到ThreadPoolExecutor的工厂。 ThreadPoolExecutor 线程池的真正实现 提供构造方法 #创建一个线程池时需要输入几个参数,如下创建一个线程池时需要输入几个参数,如下 corePoolSize 线程池的核心线程数,默认情况下,核心线程会在线程池中一直存活,即使它们处于闲置状态...

weixin_33989058的博客 113

Allegro23.1新功能之软件自带阻抗计算工具操作指导

Allegro升级到了23.1后,软件新增了一个自带阻抗计算的功能,如下图。Propagation velocity:传输速度,单位是光速的多少倍。Dielectric constant输入介电常数,这里使用常规4。新功能之软件自带阻抗计算工具。如何使用,具体操作如下。

weixin_54787054的博客 785

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

走进Java Android 的线程世界(三)Hander消息机制

ActivityThread--&gt;Android的主线程。 main方法通过Looper获取主线程、结束主线程。 H就是ActivityThread的Handler,主要包含了四大组件的启动和停止等过程。 通过ApplicationThread和AMS进行进程间通信,AMS以进程间通信的方式完成ActivityThread的请求后会回到ApplicationThread中的Binde...

weixin_34112030的博客 139

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

带你走进JAVA的世界|用心感受JAVA

一文带你走进JAVA的世界

做梦都想要三十万年薪~ 8600

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

【Java编程动手学】走进 Java 世界:全面了解 Java 语言

摘要: Java 是一种跨平台、面向对象的编程语言,自1995年发布以来广泛应用于Web、移动、企业级及大数据等领域。其核心特性包括“一次编写,到处运行”的跨平台性(基于JVM)、面向对象设计、多线程支持、自动垃圾回收和高安全性。Java经历了多个关键版本迭代,如Java 5引入泛型,Java 8加入Lambda表达式和Stream API,Java 17优化性能并新增模式匹配。其核心架构由JVM(执行字节码)、JRE(运行环境)和JDK(开发工具包)组成。Java支持OOP四大特性、泛型、函数式编程及完善

杰西笔记 1348

走进java

走进Java

m0_73503454的博客 335

一篇文章带你走进Java(保姆级)

Java是一种优秀的程序设计语言,它具有令人赏心悦目的语法和易于理解的语义。Java还是有一系列计算机软件和规范形成的技术体系,这个技术体系提供了完整的用于软件开发和跨平台部署的支持环境,并广泛应用于嵌入式系统,移动终端,企业服务器,大型机等各种场合。

cnjdd的博客 1583

带你走进Android Afinal框架的世界

1.什么是Afinal框架?       Afinal是一个开源的android的orm和ioc应用开发框架,其特点是小巧灵活,代码入侵量少。在android应用开发中,通过Afinal的ioc框架,诸如ui绑定,事件绑定,通过注解可以自动绑定。通过Afinal的orm框架,无需任何配置信息,一行代码就可以对android的sqlite数据库进行增删改查操作。同时,Afinal内嵌了finalH

七里枫香的专栏 2271

【走进android】-------WatchDog

目录 一 watchdog的创建 二 watchdog的成员和初始化 2.1 理解HandlerChecker 2.2mMonitorChecker 2.3mCompleted 2.3 watchdog的初始化 2.4 watchdog的run 方法 一 watchdog的创建 /frameworks/base/services/java/com/android/server/SystemServer.java private void startBootstrapSe...

Allen_qlp的博客 1144

Java学习笔记01 - 走进Java

一、初识Java 1、什么是Java Java是一门面向对象编程语言。它不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言功能强大并且简单易用。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。 Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点。J...

yups 1040

魔法舞台背后的守护者——安卓Android Runtime(ART)深度探秘

想象你的手机就是一座绚丽的数字剧场:应用是各路演员,用户是观众,系统是导演。但导演如何把千变万化的表演精准呈现?这一切的幕后核心,就是——。它是把代码演员变为现实舞台剧的魔法师、守夜人,也是手机流畅与高效的保障。我们常用的APP,不论是Kotlin的诗歌、Java的舞步,最终都需要由ART来“解读——转化——展现”,让虚拟文字变成真实体验。今天,我们将化身穿越者,走进ART的幕后世界,溯源它的前世今生、魔法原理及未来变革。

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 503

Android入门(一)——结构

一、Android 架构 (此图从菜鸟扒来) (1)应用程序层 短信、浏览器这些就是属于这一层。 (2)应用程序框架层 应用程序框架层主要提供了构建应用程序时用到的各种API。 (3)核心类库 包含系统库和Android运行时库, libc 库,用于仓库存储和应用数据共享的 SQLite 数据库,用于播放、录制音视频的库,用于网络安全的 SSL 库等。 (4)Linux 核心层 Linux内核层为设备的各种硬件提供了底层的驱动,如网络和大量的设备驱动,避免了兼容大量外围硬件接口所带来的不便。

rookie_0_0的博客 4891

Android-开发之从掉洞到填坑之路,走进Android架构

13.监控电量,充电时可以进行更多的数据更新,低电量时停止数据的自动更新。 **14.当系统缺少内存(而 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》 【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享 不是应用缺少内存)时,系统会调用onLowMemory()方法,所以OOM原则上无法避免。**这个嘛我遇到的少,但是还是要记住。 15.使用Account Manager来提示登录所需的信息(用户名、邮箱、密码等)。 **16

m0_64604842的博客 276
上一篇: RxJava
下一篇: QT Creator MacOS 格式化代码块快捷键
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值