lizhaotailang

macOS 安装 GCC 教程

网上的教程大多是通过安装 Xcode 实现安装 gcc 的,这种方式的花费有点太得不偿失,Xcode占据的空间是在太大,这对于128g用户简直就是噩梦。 还有就是通过homebrew安装,前提是你电脑上要安装了homebrew。 这里介绍一种简单的方法。 1. 到 https://sourceforge.net/projects/hpc/files/hpc/gcc/ 下载所需要的的gcc压缩包。 2. 下载完成后,通过 terminal 进入下载目录,即 gcc-4.8-bin.tar.gz 所在的目录。输入命令: 解压 gcc-4.8-bin.tar.gz 压缩包,注意只需要解压一次,在同一目录下得到 gcc-4.8-bin.tar 文件。 3. 继续在 terminal 中输入命令: 输入密码后,自动在当前目录下生成了usr目录。cd /user/local/bin 就可以看到所有的 `gcc 相关的命令了。当然你也可以将整个目录移动到你需要的目录。 4. 添加 gcc 路径。关掉当前 terminal ,重新新建一个 terminal 。输入如下命令:touch ~/.bash_profile…

Java 中的单例模式

什么是单例模式? 单例模式是一种对象创建模式,用于产生对象的一个具体实例,并且可以确保系统中一个类只能产生唯一的一个实例。 这样的方式能够带来两大好处: 对于频繁使用的对象,可以省略创建对象所花费的时间,对于复制的对象,这样的创建方式的开销是十分值得的; new 的次数少了,对内存的使用频率也就下降了,当然也就减轻了 GC 的压力。 设计思想 这种模式要解决的问题就是要保证应用中只存在一个对象。那怎样实现呢? 不允许其他程序new对象 在该类中创建对象 对外需要暴露一个方法,让其他获取这个对象 体现到代码中,解决办法为: 私有化构造函数 在本类中创建一个本类对象 定义一个方法,能够让其他的类获取这个对象 Code 1. 最简单的写法为 这种方式称为饿汉式。 优点 简单明了 在类加载时即完成了实例化,避免了线程同步的问题 缺点 没有使用懒加载 可能造成内存浪费 2. 变种方式 相比于第一种写法,本类中将实例化对象的代码放到了 static 代码块中。两种方法的效果其实是一样的。所以优缺点也是一样的。 3. 懒汉式(线程不安全) 优点 使用了懒加载 缺点 当有多个线程并行调用 getInstance() 的时候,就会创建多个实例。也就是说在多线程下不能正常工作。…

探索 Fragment 的生命周期

Fragment 和 Activity 类似,也有自己的生命周期,并且 fragment 的生命周期和 activity 的生命周期特别相似。 Activity 的生命周期由四种状态,运行、暂停、停止、和销毁,类似的,Fragment 也有这四种状态,只是在一些细小的地方有所不同。 Fragment 生命周期图(来自 Android 官网) 下面直接通过工程来认识 Fragment 的生命周期 首先新建 FragmentDemo 工程。 MainActivity.java 代码很简单,加载相应的布局,通过监听 button 的点击事件,加载 fragment 。 activity_main.xml MyFragment.java MyFragment 中复写了一些方法,每个方法被调用时打印日志。 ok,大功告成,现在就跑到手机上。 观察打印日志,可以看到: 按下按钮时: 此时按下 home 键: 重新回到应用: 按下 back…

实现 RecyclerView Item 的滑动删除

关于ItemTouchHelper 官方文档的解释: This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView. ItemTouchHelper是一个用于在RecyclerView中实现滑动删除和拖拽的工具类。 使用 1. 修改build.gradle文件,添加依赖。 2. 构建object与Adapter 这里假设我已经构建好了实体类CodeLanguage和adapter,在构建adapter时,需要添加一个方法。 3. 创建ItemTouchHelper.SimpleCallback子类 为了处理拖动和滑动事件,需要创建ItemTouchHelper.SimpleCallback的实现类。这里,只对滑动事件感兴趣,这是我们的callback. CodeLanguageItemTouchHelper默认的构造方法需要传入两个参数。 CodeLanguageItemTouchHelper默认需要实现两个方法onMove(),onSwiped(),onMove()是对拖拽的实现,onSwiped()是对滑动的实现。 4. 将ItemTouchHelper添加至RecyclerView 创建好自己的ItemTouchHelper类后,将它附加到RecyclerView就很简单了。在Activity或者Fragment的onCreate()方法中: 现在所有的工作已经完成。我们现在还没有添加动画,默认的动画系统已经添加。现在就可以使用了。

知乎专栏 API 分析

声明 声明:以下所有 API 均由 知乎(Zhihu.INC) 提供,本人通过非正常手段获取。获取与共享的行为有侵犯知乎权益的嫌疑。若被告知停止使用与共享,本人将及时删除整个项目。请您知悉相关情况,遵守知乎的协议。API 仅供学习交流使用,请勿用作商业用途。 说明 专栏的消息均以 JSON 格式输出; http method 均为 GET; JSON ARRAY 中的数据;只选取了具有代表性的部分进行展示. 分析 获取指定专栏的信息 例如获取知乎小管家的专栏信息 得到的信息为: followersCount: 关注该专栏的人数 creator: 该专栏的创建者信息 profileUrl: 知乎网的个人主页url bio: 官网信息中的一句话描述 hash: hash值 uid: uid isOrg: 是否为机构帐号 description: 描述 slug: slug…

浅析 Android 中 Activity 的四种启动模式

standard, singleTop, singleTask, singleInstance. 启动模式一共有上述的四种,可以在AndroidManifest.xml文件中通过给标签指定android:launchMode属性来选择启动模式。 standard standard是Activity默认的启动模式,在不进行显示指定的情况下,所有Activity都会自动的使用这种模式。Android使用返回栈来管理Activity,在standard模式下,每当启动一个新的Activity,它就会在返回栈中入栈,并处于栈顶的位置。对于使用standard模式的Activity,系统不会在乎这个Activity是否已经在返回栈中,每次启动都会创建一个新的Activity实例。 现在通过实践来体会一下standard模式,首先是新建一个ActivityTest项目,修改MainActivity的onCreate()中代码,如下所示: 代码很简单,在MainActivity的基础上启动MainActivity,从逻辑上讲没什么意义,不过我们在于研究standard模式,因此我们也就不去追究实际的用途了。另外我们还在onCreate()中添加了一句打印日志信息,打印当前Activity的实例。 现在运行程序,然后再MainActivity界面连续点击两次按钮,观察LogCat中打印的日志信息。 从打印信息中可以很清楚的看到,每次点击按钮就会创建一个新的MainActivity的实例,此时返回栈中也会存在三个MainActivity的实例,因此想要完全退出应用,必须点击三次返回键。 singleTop 在某些情况下,你可能会觉得standard模式不太合理。activity明明已经在栈顶了,为什么再次启动时还要创建一个新的Activity实例呢?这时singleTop模式就派上用场了。当Activity的启动模式被指定为singleTop时,在启动Activity时如果发现返回栈的栈顶已经是该Activity,则可以认为直接使用它,不创建新的实例。 下面看实例,修改AndroidManifest.xml中的MainActivity的启动模式为singleTop: 重新运行程序,通过LogCat查看日志信息,我们可以看到已经创建了一个新的Activity实例。 之后不管点击多少次按钮,都不会有新的打印信息出现,因为目前Activity已经处于返回栈的栈顶,每当想要再启动一个MainActivity时都会直接使用栈顶的Activity,因此MainActivity也只会有一个实例,仅按一次返回键即可退出程序。 不过当MainActivity不在栈顶时,这是再启动MainActivity,还是会创建新的实例,下面来实验一下。修改MainActivity中的代码,如下所示: 这次我们点击按钮启动的是SecondActivity。然后修改SecondActivity中onCreate()方法中的代码,如下所示: 我们在SecondActivity中的按钮的点击事件中又加入了启动MainActivity的代码。现在重新运行程序,在MainActivity界面点击按钮进入SecondActivity,然后在SecondActivity界面点击按钮,又会重新进入到MainActivity。查看LogCat中的信息: 可以看到系统创建了两个不同的MainActivity,这是由于在SecondActivity中再次启动Activity时,栈顶的Activity已经变成了SecondActivity,因此会新建一个新的MainActivity。现在按下back键就会返回到SecondActivity,再次按下back键,又会回到MainActivity,再按一次back键才会退出程序。 singleTask 使用singleTask模式可以很好的解决重复创建栈顶Activity的问题,但是正如你看到的,如果该Activity并没有处于栈顶的位置,还是可能创建多个Activity实例的。那么有没有方法可以让Activity在整个应用程序的上下文中指存在一个实例呢? 这就要借助singleTask模式来实现了。当Activity的启动模式指定为singleTask,每次启动该Activity时系统首先会在返回栈中检查是否存在该Activity的实例,如果发现已经存在则直接使用该实例,并把在这个Activity之上的所有Activity统统出栈,如果没有发现就会创建一个新的实例。 下面通过代码来直观的理解一下。修改AndroidManifest.xml文件中MainActivity的启动模式: 然后在MainActivity中添加onRestart()方法,并打印日志: 最后在SecondActivity中添加onDestroy()方法,并打印日志: 现在重新运行程序,在MainActivity界面点击按钮进入SecondActivity,然后在SecondActivity界面点按钮,又会重新进入到MainActivity。查看LogCat中的日志信息: 从打印信息中可以看出,在SecondActivity中启动MainActivity时,会发现返回栈里已经存在一个MainActivity的实例,并且是在SecondActivity的下面,于是SecondActivity会从返回栈中出栈,而MainActivity重新成为了栈顶Activity,因此MainActivity的onRestart()方法和SecondActivity的onDestroy()方法会得到执行。现在返回栈中只剩下一个MainActivity的实例了,按一下back键就可以退出程序。 singleInstance singleInstance应该是四种启动模式中最特殊也最复杂的一种了。不同于以上三种启动模式,指定为singleInstance的Activity会启用一个新的返回栈来管理这个Activity(其实如果singleTask模式指定了不同的taskAffinity,也会启动一个新的返回栈)。那么这么做有什么意义呢?假设我们的程序中有一个Activity是允许其他程序调用的,如果我们想实现其他程序和我们的程序可以共享这个Activity的实例,应该如何实现呢?使用前面三种启动模式肯定是无法实现的,因为每个程序都会有自己的返回栈,同一个Activity在不同的返回栈中入栈时必然是创建新的实例。而使用singleInstance模式就可以解决这个问题,在这种模式下会有一个单独的返回栈来管理这个Activity,不管是那个应用程序来访问这个Activity,都共用的同一个返回栈,也就解决了共享Activity实例的问题。 OK,talk is cheap,show me the code,我们还是来实践一下。修改AndroidManifest.xml中SecondActivity的启动模式: 我们先将SecondActivity的启动模式指定为singleInstance,然后修改MainActivity中onCreate()方法的代码: 在onCreate()方法中打印了当前返回栈的id。然后修改SecondActivity中onCreate()方法的代码: 同样在onCreate()方法中打印了当前返回栈的id,然后又修改了按钮点击事件的代码,用于启动ThirdActivity。最后修改ThirdActivity中onCreate()方法的代码: 仍然是在onCreate()方法中打印了当前返回栈的id。现在重新运行程序,在MainActivity界面中点击按钮进入到SecondActivity,然后在SecondActivity中点击按钮进入到ThirdActivity。查看LogCat中的打印信息:…

进程与线程之间的关系

什么是进程? 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的独立单位。进程拥有一个完整的虚拟空间地址,并不依赖线程而独立存在。 什么是线程? 线程是进程的一个实体,是cpu调度和分配的基本单位。它是进程更小的能独立运行的基本单位。线程本身并不拥有系统资源,运行是只是暂用一些计数器、寄存器和栈。 进程与线程之间的关系 简单来说,一个程序至少拥有一个进程,而一个进程至少拥有一个线程。 一个线程可以创建和撤销另外一个线程,同一个进程中可以有多个线程并发的执行。 线程更加接近于执行体的概念,它可以同进程中的其他线程共享数据,但是拥有独立的栈空间,拥有独立的执行序列。 进程与线程的区别 进程与线程的主要区别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃之后,在保护模式对其他进程没有影响,线程只是进程的不同执行路径。线程有自己独立的堆栈和局部变量,但是没有独立的地址空间,一个线程死掉那么整个进程也就死掉了,所以多进程的应用要比多线程的应用更加健壮。但是进程在切换时耗费的资源也比较多,效率也要更差,所以在并发性要求高又要共享变量数据,只能靠线程,而不是进程。 在执行过程中,每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多线程执行控制。 从逻辑上看,多线程的意义在于在一个应用程序当中,有多个执行部分可以同时执行。但是操作系统并没有将多个线程看作多个独立的应用,来实现进程的调度和管理以及资源分配。

浅谈 Android 中的 ANR 现象

什么是ANR ANR,Application Not Responding,即程序未响应。发生ANR时,系统会显示一个dialog,提示用户出现了ANR,用户可以选择“等待”,或者是“强制关闭”,结束应用。ANR同崩溃一样,是在开发过程中应该避免的。 什么会触发ANR 主线程被IO操作阻塞。(文档中特别强调:you should not perform the work on the UI thread(不要在UI线程中进行IO操作))。 主线程中存在耗时的操作。 主线程中错误操作。如Thread.wait()或Thread.sleep()等。 在Android中,应用程序的响应是受到Activity Manager 和 Window Manageer系统服务的。一旦出现以下情况,Android系统就会展示dialog: 5秒内没有相应触摸操作。(No response to an input event (such as key press or screen touch events) within 5 seconds.) 广播接收器在10内没有执行完成。(A…