Diycode开源项目 ImageActivity分析
1.首先看一下效果
1.1做成了一个GIF
1.2.我用格式工厂有点问题,大小无法调到手机这样的大小,目前还没有解决方案。
1.3.网上有免费的MP4->GIF,参考一下这个网站吧。
1.4.讲解一下这个图片吧,首先是从话题中点击了其中一张图片,进入图片Activity,
然后可以自由放大,自由翻转。
2.分析一下继承的BaseImageActivity
2.1因为ImageActivity继承了BaseImageActivtiy,首先看看源代码。
/*
* Copyright 2017 GcsSloop
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Last modified 2017-03-15 20:02:59
*
* GitHub: https://github.com/GcsSloop
* Website: http://www.gcssloop.com
* Weibo: http://weibo.com/GcsSloop
*/ package com.gcssloop.diycode.base.app; import android.content.Intent; import java.util.ArrayList; /**
* 对数据进行预处理
*/
public abstract class BaseImageActivity extends BaseActivity {
public static final String ALL_IMAGE_URLS = "all_images";
public static final String CURRENT_IMAGE_URL = "current_image"; protected static final String MODE_NORMAL = "normal";
protected static final String MODE_ERROR = "error";
protected String mCurrentMode = MODE_NORMAL; protected ArrayList<String> images = new ArrayList<>(); // 所有图片
protected String current_image_url = null; // 当前图片
protected int current_image_position = 0; // 当前图片位置 @Override
protected void initDatas() {
super.initDatas(); // 初始化图片 url 和 图片集合,保证两个数据都存在
Intent intent = getIntent(); // 没有传递当前图片,设置模式为错误
String imageUrl = intent.getStringExtra(CURRENT_IMAGE_URL);
if (imageUrl == null || imageUrl.isEmpty()) {
toastShort("没有传递图片链接");
mCurrentMode = MODE_ERROR;
return;
}
mCurrentMode = MODE_NORMAL; ArrayList<String> temp = intent.getStringArrayListExtra(ALL_IMAGE_URLS);
if (temp == null || temp.size() <= 0) {
// 记录当前图片,计算位置
images.clear();
images.add(imageUrl);
} else if (temp.size() > 0) {
// 如果图片集合大于0
images = new ArrayList<>(temp);
} if (!images.contains(imageUrl)) {
images.add(imageUrl);
} current_image_url = imageUrl;
current_image_position = images.indexOf(current_image_url);
}
}
2.2这里需要回顾一下BaseActivity。
BaseActivity==>主要提供了项目本身API提供的Diycode类,ViewHolder类,Toast类,两个抽象方法。ActionBar。结束
当前活动。
打开活动。
2.3.私有成员变量。
·存放图片链接的一个ArrayList<String>
·存放当前图片的链接current_image_url
·存放当前图片位置,整型current_image_positon
2.4.注意点,Override一个在基类中已经实现过的函数。
重载,也是可以Override的。以前理解的Override就是抽象方法,接口方法。这里又涨知识了。
如果写了一个父类中有的方法,就相当于重载了父类中的方法,就不会执行父类中的那个方法,而是执行自己的方法了。
名字是一样的。
2.5.在BaseActivity中写了一个空的initDatas方法。而且规定了这个方法执行的顺序。
然后在子类BaseImageActivity中重载这个方法。
这个类主要处理图片数据的。
2.6分析这个重载方法。
2.6.1首先从intent中获得当前图片,如果没有,设置模式为错误。否则,设置模式为正常。
2.6.2然后从intent中获得所有图片集合,如果没有,就把当前图片加进images去,如果有,就将集合加到一个images中。
2.6.3然后它还判断了一下images中是否包含了当前url,应该是双保险吧,感觉没必要。
2.6.4最后,就把当前图片和当前位置更新了一下。
3.分析一下图片缓存DiskImageCache
3.1首先看看在ImageActivity中定义的一个变量。DiskImageCache mCache;源代码如下:
/*
* Copyright 2017 GcsSloop
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Last modified 2017-03-12 00:56:52
*
* GitHub: https://github.com/GcsSloop
* Website: http://www.gcssloop.com
* Weibo: http://weibo.com/GcsSloop
*/ package com.gcssloop.diycode.base.webview; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.StatFs;
import android.support.annotation.NonNull;
import android.util.Log; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Comparator; public class DiskImageCache {
private static final String CACHE_SUFFIX = ".cache"; private static final int MB = 1024 * 1024;
private static final int CACHE_SIZE = 50; // 缓存占用空间大小
private static final int FREE_SD_SPACE_NEEDED_TO_CACHE = 10; // 为 SD 卡保留多少空间 private File cacheDir; public DiskImageCache(Context context) {
cacheDir = getDiskCacheDir(context, "web-image");
// 整理缓存
organizeCache(cacheDir);
} /**
* 从缓存中获取图片
**/
public Bitmap getBitmap(final String key) {
final String path = getCachePath(key);
File file = new File(path);
if (file.exists()) {
Bitmap bmp = BitmapFactory.decodeFile(path);
if (bmp == null) {
file.delete();
} else {
updateFileTime(path);
return bmp;
}
}
return null;
} /**
* 将图片存入文件缓存
**/
public void saveBitmap(String key, Bitmap bm) {
if (bm == null) {
return;
}
//判断sdcard上的空间
if (FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
return; //SD空间不足
}
File file = new File(getCachePath(key));
try {
file.createNewFile();
OutputStream outStream = new FileOutputStream(file);
bm.compress(Bitmap.CompressFormat.PNG, 100, outStream);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
Log.w("ImageFileCache", "FileNotFoundException");
} catch (IOException e) {
Log.w("ImageFileCache", "IOException");
}
} /**
* 保存 bytes 数据
*
* @param key url
* @param bytes bytes 数据
*/
public void saveBytes(String key, byte[] bytes) {
if (bytes == null) {
return;
}
//判断sdcard上的空间
if (FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
return; //SD空间不足
}
File file = new File(getCachePath(key));
try {
file.createNewFile();
OutputStream outStream = new FileOutputStream(file);
outStream.write(bytes);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
Log.w("ImageFileCache", "FileNotFoundException");
} catch (IOException e) {
Log.w("ImageFileCache", "IOException");
}
} /**
* 获取一个本地缓存的输入流
*
* @param key url
* @return FileInputStream
*/
public FileInputStream getStream(String key) {
File file = new File(getCachePath(key));
if (!file.exists())
return null;
try {
FileInputStream inputStream = new FileInputStream(file);
return inputStream;
} catch (FileNotFoundException e) {
Log.e("getStream", "FileNotFoundException");
e.printStackTrace();
}
return null;
} /**
* 获取本地缓存路径
*
* @param key url
* @return 路径
*/
public String getDiskPath(String key) {
File file = new File(getCachePath(key));
if (!file.exists())
return null;
return file.getAbsolutePath();
} /**
* 是否有缓存
*
* @param key url
* @return 是否有缓存
*/
public boolean hasCache(String key) {
File file = new File(getCachePath(key));
return file.exists();
} /**
* 计算存储目录下的文件大小,
* 当文件总大小大于规定的CACHE_SIZE或者sdcard剩余空间小于FREE_SD_SPACE_NEEDED_TO_CACHE的规定
* 那么删除40%最近没有被使用的文件
*/
private boolean organizeCache(@NonNull File cacheDir) {
File[] files = cacheDir.listFiles();
if (files == null) {
return true;
}
if (!Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
return false;
} int dirSize = 0;
for (int i = 0; i < files.length; i++) {
if (files[i].getName().contains(CACHE_SUFFIX)) {
dirSize += files[i].length();
}
} if (dirSize > CACHE_SIZE * MB || FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) {
int removeFactor = (int) ((0.4 * files.length) + 1);
Arrays.sort(files, new FileLastModifSort());
for (int i = 0; i < removeFactor; i++) {
if (files[i].getName().contains(CACHE_SUFFIX)) {
files[i].delete();
}
}
} if (freeSpaceOnSd() <= CACHE_SIZE) {
return false;
} return true;
} /**
* 修改文件的最后修改时间
**/
public void updateFileTime(String path) {
File file = new File(path);
long newModifiedTime = System.currentTimeMillis();
file.setLastModified(newModifiedTime);
} /**
* 计算sdcard上的剩余空间
**/
private int freeSpaceOnSd() {
StatFs stat = new StatFs(Environment.getExternalStorageDirectory().getPath());
double sdFreeMB = ((double) stat.getAvailableBlocks() * (double) stat.getBlockSize()) / MB;
return (int) sdFreeMB;
} /**
* 根据文件的最后修改时间进行排序
*/
private class FileLastModifSort implements Comparator<File> {
public int compare(File arg0, File arg1) {
if (arg0.lastModified() > arg1.lastModified()) {
return 1;
} else if (arg0.lastModified() == arg1.lastModified()) {
return 0;
} else {
return -1;
}
}
} /**
* 获取缓存文件的绝对路径
*/
private String getCachePath(String key) {
return cacheDir.getAbsolutePath() + File.separator + convertKey(key);
} /**
* 获取磁盘缓存文件夹 优先获取外置磁盘
*
* @param context 上下文
* @param uniqueName 自定义名字
*/
public File getDiskCacheDir(Context context, String uniqueName) {
String cachePath;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
|| !Environment.isExternalStorageRemovable()) {
cachePath = context.getExternalCacheDir().getPath();
} else {
cachePath = context.getCacheDir().getPath();
}
File cacheDir = new File(cachePath + File.separator + uniqueName);
if (!cacheDir.exists())
cacheDir.mkdir();
return cacheDir;
} /**
* 哈希编码
*/
public String convertKey(String key) {
String cacheKey;
try {
final MessageDigest mDigest = MessageDigest.getInstance("MD5");
mDigest.update(key.getBytes());
cacheKey = bytesToHexString(mDigest.digest());
} catch (NoSuchAlgorithmException e) {
cacheKey = String.valueOf(key.hashCode());
}
return cacheKey + CACHE_SUFFIX;
} private String bytesToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(0xFF & bytes[i]);
if (hex.length() == 1) {
sb.append('0');
}
sb.append(hex);
}
return sb.toString();
} }
3.2定义的常量及变量预览。
3.3.构造函数就一个。实现方法在后面。
3.4.如何从缓存中获取图片(通过一个String返回一个Bitmap),这个项目暂时没有用到。
3.5.如何将图片存入文件缓存?(将一个bitmap,存放一个缓存路径为一个key下)
3.6.如何保存bytes数据?(也是存放到一个key中)
3.7.如何获取一个本地缓存的输入流?(通过一个key获得FileInputStream)
3.8.如何获取本地缓存路径?(通过一个key得到一个String)
3.9.如何判断是否有缓存?(通过一个key返回boolean)
3.10.然后是关键的整理存储空间了。这个删除文件很关键,不然数据会越来越大的。
3.11.如何修改文件的最后修改时间?(参数为文件path)
3.12.如何计算sdcard上的剩余空间?
3.13.如何根据文件的最后修改时间进行排序?(继承了一个Comparator<File>的内部类)
FileLastModifSort其实就是一个类,类中有一个比较的函数,有两个File的参数,比较哪个更加最后而已。
3.14.如何获取缓存文件的绝对路径?(通过key得到一个String)
3.15.如何获取磁盘缓存文件夹,优先获取外置磁盘?(参数为context和一个string返回一个File)
3.16.什么是哈希编码?(参数为key返回一个String)
通过MD5加密后加了一个后缀为.cache,返回这个字符串。
3.17.bytes数组转化为哈希String?(参数为byte[]返回一个String)
这个在3.16.哈希编码中用到了,就是系统函数很多会转化为bytes,这个函数就是将byte[]类型的数据整合成String,
然后再处理逻辑。
这个DiskImageCache比较长,主要处理的就是一些缓存问题了,图片缓存,和本地的存储器挂钩了,所以就有很多函数
要调用。
4.回到ImageActivity
4.1这里首先复写了一个getLayoutId,返回一个资源id,其实就是ImageActivity布局
贴一下activity_image源代码。
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2017 GcsSloop
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~
~ Last modified 2017-03-15 23:45:17
~
~ GitHub: https://github.com/GcsSloop
~ Website: http://www.gcssloop.com
~ Weibo: http://weibo.com/GcsSloop
--> <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.gcssloop.diycode.activity.ImageActivity"> <android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/> <RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"> <android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager> <com.rd.PageIndicatorView
android:id="@+id/pageIndicator"
android:layout_marginBottom="16dp"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:piv_viewPager="@id/view_pager"
app:piv_animationType="worm"
app:piv_autoVisibility="false"
app:piv_radius="4dp"
app:piv_padding="12dp"
app:piv_unselectedColor="@color/diy_gray2"
app:piv_selectedColor="@color/diy_red"
/> </RelativeLayout> </LinearLayout>
4.2分析一下布局代码的结构
4.3.和真实页面对比一下。
4.4.这里有一个新的知识点==>PageIndicatorView
这是一个开源框架。挺不错的。简单实用。
作用就是当页面在切换时,一个提示作用,下面的小红点会告诉用户这是第几张图或者第几个页面。
4.5.然后是复写一个initViews方法。
4.5.1.注意,这个函数在initDatas之后调用。initDatas()函数在BaseImageActivity中调用了。
4.5.2.这里面通过setTitle设置了标题栏的查看图片。
4.5.3.这里从参数ViewHolder中获得了布局中的ViewPager,显然ViewHolder中BaseActivity中定义
然后ViewHolder初始化其实也是在BaseActivity中进行的,利用了一个抽象函数getLayoutId()
然后initData(),然后initViews(),所以这个ImageActivity才能直接获得这个ViewPager的Id。
4.5.4.这里看一下initViews中的部分代码。
对于getLayoutInflater不太理解,参考一下这篇文章。
4.5.4.1.它的作用类似于findViewById()。
4.5.4.2.LayoutInflater是用来找res/layout/下的xml布局文件,并且实例化。
4.5.4.3.FindViewById是找xml布局文件下的具体widget控件(如Button、TextView等)
4.5.5.这里继续initViews中的部分代码。
4.5.5.1.这里是在ImageActivity中定义的布局文件中的viewPager设置适配器的过程。
4.5.5.2.首先是复写了getCount方法,直接返回图片的张数。
4.5.5.3.然后是复写了isViewFromObject方法,两个参数(View,Object),使两者相等。
4.5.5.4.然后复写了一个关键的函数,instantiateItem(ViewGroup,int)
4.5.5.6.这里不得不提一下的是PhotoView。
也是第三方开源库,支持双指缩放,旋转。
看一下效果图吧!
4.5.5.7.分析一下instantiateItem==>这个方法返回一个对象,这个对象表明了PagerAdapter适配器选
择那个对象放在当前的ViewPager中。
然后这里还处理了缓存,如果缓存中有,就利用Glide.with(context).load(file).into()
如果缓存中没有,就利用Glide.with(context).load(图片url).into()方法
然后将这个photoView添加到容器中,这个容器就是instantiateItem中的第一个参数。
4.5.5.8.分析一下复写的destroyItem()方法,3个参数(ViewGroup,int,Object)
这个方法,是从ViewGroup中移除当前View。
4.5.5.9.然后将viewPager确定到第几项。
调用了基类BaseImageActivity中的静态常量current_image_position。
这样可以确定指示剂的位置。
4.6.然后回到ImageActivity中,最后一个函数是loadImage(string,photoView)
作用:给一个url和一个photoView,加载一张图到photoView中。
这里用到了一个第三方库。图片加载库。
源码如下:
这个应该是设置了缓存策略。
5.总结一下
5.1.首先理解一下哪里会用到ImageActivity这个活动,这个活动不是局限于某一个模块,而是所有地方,只要包含了图片
的地方,都是有可能调用intent来跳转到这里的。所以这个有点像之前做的大学喵,点击图片查看大图,支持缩放。
5.2.然后理解一下为什么这个ImageActivity要继承一个BaseImageActivity,这个BaseImageActivity实际上是一个抽象类,
定义了所有图片数据,所以真实数据在这里面处理,确定当前图片url,当前是第几个图片。
5.3.然后定义了一个DiskImageCache,主要是处理图片缓存的,基本上每个项目都会涉及到图片缓存,而且这些方法都是
必须实现而且基本一样,所以今后的项目也可以参考一下这个类,封装好的,耦合很低。
5.4.然后是一个imageActivity的布局,通过实现了BaseActivity中的抽象函数getLayoutId,来获得这个布局的资源id。
然后在initViews中的参数holder中,利用holder.get(R.id.view_pager)就能访问到这个ViewPager。
5.5.初始化view,注意是在initDatas调用之后,因为有了数据,才能填充到真实的视图。这里可以setTilte()来设置标题。
然后就是一些缓存处理了。
5.6.真正的图片要加载处理,必须要有一个adapter,所以这里new了一个PagerAdapter,实现了4个必须实现的方法。主要
逻辑在instantiateItem(ViewGroup container,int position)中处理,比如开启photoView缩放功能。以及缓存处理。
5.7.initViews函数执行结束之前一定要设置这个viewPager当前的页面,调用setCurrentItem(int)即可。
这个int其实是在父类中定义,因为这个是继承了父类,也可以直接调用父类中的变量。
5.8.最后是一个图片缓存策略,因为是灰色的,也没有执行,可以也不是必须要实现的。但是要是不得不说Glide有点强大,
特别是处理图片问题,图片缓存问题,图片加载问题。有空再深究一下。
Diycode开源项目 ImageActivity分析的更多相关文章
- Diycode开源项目 BaseApplication分析+LeakCanary第三方+CrashHandler自定义异常处理
1.BaseApplication整个应用的开始 1.1.看一下代码 /* * Copyright 2017 GcsSloop * * Licensed under the Apache Licens ...
- DiyCode开源项目 BaseActivity 分析
1.首先将这个项目的BaseActivity源码拷贝过来. /* * Copyright 2017 GcsSloop * * Licensed under the Apache License, Ve ...
- Diycode开源项目 TopicContentActivity分析
1.效果预览以及布局分析 1.1.实际效果预览 左侧话题列表的布局是通过TopicProvider来实现的,所以当初分析话题列表就没有看到布局. 这里的话题内容不是一个ListView,故要自己布局. ...
- Diycode开源项目 UserActivity分析
1.效果预览 1.1.实际界面预览 1.2. 这是MainActivity中的代码 这里执行了跳转到自己的用户界面的功能. 1.3.点击头像或者用户名跳转到别人的页面 UserActivity的结构由 ...
- Diycode开源项目 LoginActivity分析
1.首先看一下效果 1.1.预览一下真实页面 1.2.分析一下: 要求输入Email或者用户名,点击编辑框,弹出键盘,默认先进入输入Email或用户名编辑框. 点击密码后,密码字样网上浮动一段距离,E ...
- Diycode开源项目 MainActivity分析
1.分析MainActivity整体结构 1.1.首先看一下这个界面的整体效果. 1.2.活动源代码如下 /* * Copyright 2017 GcsSloop * * Licensed under ...
- DiyCode开源项目 AboutActivity分析
1.首先看一下效果 这是手机上显示的效果: 1.1首先是一个标题栏,左侧一个左箭头,然后一个图标. 1.2然后下方是一个可以滑动的页面. 1.3分成了7个部分. 1.4DiyCode的图标. 1.5然 ...
- DiyCode开源项目 TopicActivity 分析
1.首先看看TopActivity效果. 2.TopicActivity是一个继承BaseActivity的.前面分析过BaseActivity了.主要有一个标题栏,有返回的图标. 3.贴一下T ...
- Diycode开源项目 SitesListFragment分析
1.效果预览 1.1.网站列表实际界面 1.2.注意这个界面没有继承SimpleRefreshRecycleFragment 前面的话题和新闻继承了SimpleRefreshRecyclerFragm ...
随机推荐
- jquery jquery中是否加()的问题
自己总结的,慢慢修改再: 1带上()代表立即执行 去掉()代表当有事件发生的时候,我再执行
- [翻译] Facebook HHVM 团队封闭开发三周成果展
本人翻译的一篇文章,首发于伯乐在线. [补充信息]HipHop for PHP是一系列PHP脚本语言的程式码转换器的集合,它包含HPHPc.HPHPi.HPHPd以及HHVM,这四个脚本引擎各有所不同 ...
- css 选择器 & UI元素的伪类选择器 & 伪元素选择器
UI元素的伪类选择器 1. :focus 用来选取获取焦点事件 2. :enabled 用来指定当元素处于可用状态时的样式 3. :disable 用来指定元素处于不可用时的状态 表单里应用 ...
- Linux 下查找指令
原文链接:http://www.cnblogs.com/sunleecn/archive/2011/11/01/2232210.html whereis <程序名称>查找软件的安装路径-b ...
- (转载)C#中的lock关键字
lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断.这是通过在代码块运行期间为给定对象获取互斥锁来实现的. 先来看看执行过程,代码示例如下: 假设线程A先执行,线程B稍微慢一点.线程A执 ...
- cocos2d-x 学习资料汇总
cocos2d-x配置问题 - 我要飞的更高 - 博客频道 - CSDN.NET Cocos2d-x win7 + vs2010 配置图文详解(亲测) - 子龙山人 - 博客园 WINDONWS7+V ...
- alias 新的命令='原命令 -选项/参数'。举例说明,alias l=‘ls -lsh' 将重新定义 ls 命令,现在只需输入 l 就可以列目录了。
alias 新的命令='原命令 -选项/参数'.举例说明,alias l=‘ls -lsh' 将重新定义 ls 命令,现在只需输入 l 就可以列目录了.
- HTML和CSS中一些有趣的
CSS Rese http://yui.yahooapis.com/3.18.1/build/cssreset/cssreset-min.css <link rel="styleshe ...
- Ubuntu 16.04 开启休眠功能
因为休眠功能在部分计算机无法正常工作,所以Ubuntu默认是不开启休眠功能. 要想开启休眠功能先进行如下测试: 1.先检查是否有交换分区(swap),如果有确认交换分区至少和实际可用内存一样大. 2. ...
- Java的几种加载驱动的方法
1.Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); 2.DriverManager.registerD ...