美文网首页
Android 学习笔记

Android 学习笔记

作者: 依然范特西_ | 来源:发表于2018-08-12 18:54 被阅读0次
  1. 对一个服务既调用了startService()方法,又调用了bindService()方法的,这种情况下要同时调用stopService()和unbindService()方法,onDestroy()方法才会执行。

  2. Postfix Completion
    http://www.cnblogs.com/huilixieqi/p/6496795.html

  3. 使用<ViewStub>标签与设置View.GONE的区别:
    <ViewStub>标签只会在显示时,才去渲染整个布局,而View.GONE,在初始化布局树的时候就已经添加在布局树上了,相比之下<ViewStub>标签的布局具有更高的效率。

  4. adb nodaemon server
    这是一条神奇的指令,他将告诉你为啥你启动不了你的adb,这样按照他的指示,你就可以解决你的问题了。

  5. 导入Android Studio项目时,如果该项目的gradle版本和本地的不一致, AS就会去下载这个版本的Gradle。解决这个问题,可以在本地用当前版本的Gradle创建一个正常的项目, 然后用本地项目中的 “gradle” 文件夹 去替换掉要导入的项目中的文件夹。再打开项目时就可以使用本地的gradle对项目进行编译了。

  6. Android开发技巧集合
    https://7449.github.io/2017/02/09/Android_DevelopmentSkills/

  7. dp与sp的区别:

  1. 生成aar、Jar包
    http://blog.csdn.net/getchance/article/details/47257389
    http://www.cnblogs.com/xxdh/p/6703746.html

  2. Gradle的一些基本依赖配置方式如下:

  • 将某个目录下所有符合扩展名的文件作为依赖
compile fileTree(dir:'xxx',include:['*.jar','*.xxx'])
  • 配置Maven库为依赖
compile 'com.xx.xx:ProjectName:Version'
  • 配置另一个module作为本Module的依赖,被依赖的Module必须被导入到当前工程中
compile project(':otherModule')
  • 配置某个jar包作为依赖
compile file('xxx.jar')
  1. 在打包aar(笔记8)时,build/ouputs/aar里面只有debug版本,将这个包引入其他项目无法使用。然后我在终端运行
gradlew assembleRelease

之后,再回到文件夹,这时候有了release版本,将这个release版本引入其他项目就可以运行了。

  1. 在导入aar包之后,运行时报错如下
Error:Execution failed for task ':app:processDebugManifest'.
> Manifest merger failed with multiple errors, see logs

可以进入如下界面查看错误信息

image
  1. 指定.so文件目录为libs
sourceSets {
    main {
        jniLibs.srcDirs = ['libs']
    }
}
  1. 解决
Error:The number of method references in 
a .dex file cannot exceed 64K.
image image
  1. 找不到.so文件
java.lang.UnsatisfiedLinkError:
dalvik.system.PathClassLoader

如果文件位置正确,且gradle配置正确时,注意查看是不是armeabi, armeabi-v7a等文件夹里面都含有所需.so文件,因为android 5.0及以上只拷贝一个最合适的目录下的so库到系统指定目录,所以必须保证每个文件夹下都有完整的so文件。


另外,还需要保证项目导入的aar文件中的armeabi,armeabi-v7a等文件夹与app/jniLibs下的文件夹一致。如果项目jniLibs下只有armeabi文件夹,最好把aar中除armeabi之外的文件夹删掉。

  1. 在项目中将dp转化为px(以40dp为例)。
mDensity = getResources().getDisplayMetrics().density;

mHeight = (int) (mDensity * 40);
  1. 开启WIFI调试

android手机接上电脑,开启CMD命令行

输入:adb tcpip 5555

输入:adb connect 192.168.0.xxx(手机IP)

即可实现wifi无线调试

  1. 读取txt文件内容

  2. android读取txt文件中文乱码的问题
    txt文件的默认编码方式是ANSI,改为utf-8导入项目即可。

  3. Proguard高级混淆
    原文地址 来自drakeet

    image
    image
  4. 解决Gradle下载慢的问题

    使用阿里云的国内镜像仓库地址,就可以快速的下载需要的文件修改项目根目录下的文件 build.gradle :

buildscript {
    repositories {
        maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
    }
}

allprojects {
    repositories {
        maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
    }
}

然后选择重新构建项目就可以了

  1. style

[图片上传失败...(image-f125a8-1534071069706)]

  1. 解决Toolbar中menu栏遮挡标题栏
<resources>

    <!-- Base application theme. -->
    <style name="Theme.ToolBar.Menu" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="android:colorPrimary">@color/color_primary</item>
        <item name="android:colorPrimaryDark">@color/color_primaryDark</item>
        <item name="android:colorAccent">@color/color_accent</item>
        <item name="android:navigationBarColor">@color/color_primary</item>
        
        <!-- 注意这里没有"android:" -->
        <item name="actionOverflowMenuStyle">@style/OverflowMenuStyle</item>

    </style>



    <!--把该属性改为false即可使menu位置位于toolbar之下-->
    <style name="OverflowMenuStyle" parent="Widget.AppCompat.Light.PopupMenu.Overflow">
        <item name="overlapAnchor">false</item>
        <item name="android:dropDownVerticalOffset">0dp</item>
    </style>

</resources>
  1. Fragment调用Activity中的方法
假如 父Activity的类名叫 ParentActivity,有一个test()方法
在Fragment中调用其实很简单,代码如下:

ParentActivity parentActivity = (ParentActivity ) getActivity();
parentActivity.test();

24. SpannedString , SpannableString

image

String

A String is immutable (ie, the text can't change). It also doesn't have any spans associated with it. (Spans are ranges over the text that include styling information like color, highlighting, italics, links, etc.) So you can use a String when your text doesn't need to be changed and doesn't need any styling.

StringBuilder

A StringBuilder has mutable text, so you can modify it without creating a new object. However, it doesn't have any span information. It is just plain text. So use a StringBuilder when you need to change the text, but you don't care about styling it.

SpannedString

A SpannedString has immutable text (like a String) and immutable span information. It is a concrete implementation of the requirements defined by the Spanned interface. Use a SpannedString when your text has style but you don't need to change either the text or the style after it is created.

Note: There is no such thing as a SpannedStringBuilder because if the text changed then the span information would also very likely have to change.

SpannableString

A SpannableString has immutable text, but its span information is mutable. It is a concrete implementation of the requirements defined by the Spannable interface. Use a SpannableString when your text doesn't need to be changed but the styling does.

SpannableStringBuilder

A SpannableStringBuilder has both mutable text and span information. It is a concrete implementation of the requirements defined by the Spannable and Editable interfaces (among others). Use a SpannableStringBuilder when you will need to update the text and its style.

CharSequence

A CharSequence is an interface and not a concrete class. That means it just defines a list of rules to follow for any class that implements it. And all of the classes mentioned above implement it. So you can use a CharSequence when you want to generalize the type of object that you have for maximum flexibility. You can always downcast it to a String or SpannableStringBuilder or whatever later if you need to.

image
  1. 获取系统分配给应用程序的内存大小(单位:KB)
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
//获取系统当前使用的语言
String lan =Locale.getDefault().getLanguage();
//获取区域
String country =Locale.getDefault().getCountry();
//设置成简体中文的时候,getLanguage()返回的是zh,getCountry()返回的是cn.
  1. 让一个方法接受接口类型的参数,是一种让任何类都能对该方法进行适配的方式,只需要让类实现这个接口。如果想让这个方法作用于一个已存在的类,可以使用适配器模式,写一个新类以已存在的类为成员对象,或者继承它,并实现这个接口。

  2. Dialog的style文件属性

<style name="dialog" parent="@android:style/Theme.Dialog">
    //Dialog的windowFrame框为无
    <item name="android:windowFrame">@null</item>
    //是否浮现在activity之上
    <item name="android:windowIsFloating">true</item>
    //是否半透明
    <item name="android:windowIsTranslucent">true</item>
    //是否显示title
    <item name="android:windowNoTitle">true</item>
    //设置dialog的背景
    <item name="android:background">@android:color/transparent</item>
    //显示区域背景是否透明
    <item name="android:windowBackground">@android:color/transparent</item>
    //就是用来控制灰度的值,当为1时,界面除了我们的dialog内容是高亮显示的,dialog以外的区域是黑色的,完全看不到其他内容,系统的默认值是0.5
    <item name="android:backgroundDimAmount">0.5</item>
    //显示区域以外是否使用黑色半透明背景
    <item name="android:backgroundDimEnabled">true</item>
</style>
  1. Android 从网络中获取数据时 产生部分数据乱码的解决
public static String doGet(String urlStr) throws CommonException  
    {  
        StringBuffer sb = new StringBuffer();  
        try  
        {  
            URL url = new URL(urlStr);  
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
            conn.setRequestMethod("GET");  
            conn.setConnectTimeout(5000);  
            conn.setDoInput(true);  
            conn.setDoOutput(true);  
  
            if (conn.getResponseCode() == 200)  
            {  
                InputStream is = conn.getInputStream();  
                int len = 0;  
                byte[] buf = new byte[1024];  
  
                while ((len = is.read(buf)) != -1)  
                {  
                    sb.append(new String(buf, 0, len, "UTF-8"));  
                }  
  
                is.close();  
            } else  
            {  
                throw new CommonException("访问网络失败!");  
            }  
  
        } catch (Exception e)  
        {  
            throw new CommonException("访问网络失败!");  
        }  
        return sb.toString();  
    }  

可能是由于采用字节流从网络读取数据,且每次读取1024个字节,读取完成后能后强制转化为字符串,又因为使用编码为UTF-8,UTF-8是一种变长码(英文1个字节,中文两个字节),所以1024可能会造成刚好截取了某个汉字的一半(前一个字节),然后转化为字符串时造成乱码。唯一不理解的在java环境下,使用控制台打印出是没有乱码的。如果你有不同的理解欢迎留言探讨。
于是把读取数据的代码从字节流改成字符流,修改后的代码为:

public static String doGet(String urlStr) throws CommonException  
    {  
        StringBuffer sb = new StringBuffer();  
        try  
        {  
            URL url = new URL(urlStr);  
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
            conn.setRequestMethod("GET");  
            conn.setConnectTimeout(5000);  
            conn.setDoInput(true);  
            conn.setDoOutput(true);  
  
            if (conn.getResponseCode() == 200)  
            {  
                InputStream is = conn.getInputStream();  
                InputStreamReader isr = new InputStreamReader(is,"UTF-8");  
                int len = 0;  
                char[] buf = new char[1024];  
  
                while ((len = isr.read(buf)) != -1)  
                {  
                    sb.append(new String(buf, 0, len));  
                }  
  
                is.close();  
                isr.close();  
            } else  
            {  
                throw new CommonException("访问网络失败!");  
            }  
  
        } catch (Exception e)  
        {  
            throw new CommonException("访问网络失败!");  
        }  
        return sb.toString();  
    }  
  1. 矩阵前乘、后乘
前乘(pre)

前乘相当于矩阵的右乘(原矩阵在前):

M' = M * S
后乘(post)

后乘相当于矩阵的左乘(原矩阵在后):

M' = S * M
设置(set)

设置使用的不是矩阵乘法,而是直接覆盖掉原来的数值,所以,使用设置可能会导致之前的操作失效。

//返回的是单位矩阵  
Matrix matrix = new Matrix();
  1. 判断app是否第一次启动:
SharedPreferences setting = getSharedPreferences(YOUR_PREF_FILE_NAME, 0);  
   Boolean user_first = setting.getBoolean("FIRST",true);  
   if(user_first){//第一次  
        setting.edit().putBoolean("FIRST", false).commit();  
        Toast.makeText(MainActivity.this, "第一次", Toast.LENGTH_LONG).show();  
    }else{  
       Toast.makeText(MainActivity.this, "不是第一次", Toast.LENGTH_LONG).show();  
   } 
  • 获取顶部status bar 高度
    
private int getStatusBarHeight() {
    Resources resources = mActivity.getResources();
    int resourceId = resources.getIdentifier("status_bar_height", "dimen","android");
    int height = resources.getDimensionPixelSize(resourceId);
    Log.v("dbw", "Status height:" + height);
    return height;
}
  •       获取底部 navigation bar 高度
    
private int getNavigationBarHeight() {
    Resources resources = mActivity.getResources();
    int resourceId = resources.getIdentifier("navigation_bar_height","dimen", "android");
    int height = resources.getDimensionPixelSize(resourceId);
    Log.v("dbw", "Navi height:" + height);
    return height;
}
  1. 通常说的screen density指的是ppi(pixs per inch), 也等于dpi(dots per inch), 这个值一般为120, 160, 240, 320。当ppi等于160时,1dp为1px。
screen density(ppi) = screen width (or height) in pixels / screen width (or height) in inches

1dp = (screen density / 160) px

项目中获取屏幕宽高和密度方法:

 DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
 
int width = dm.widthPixels;  
int height = dm.heightPixels;

//对应上面提到的screen density
int density = dm.densityDpi;

//注意这个density不是上面说的screen density
//可以理解为1dp对应的px
float fdensity = dm.density;

//dp转px, 如 50dp
float result = 50 * fdensity;
/**
     * 获取传入日期的前一天
     * @param date
     * @return
     */
    public static String getLastDay(Date date, String fmt) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // -1 前一天, 1 后一天
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        date = calendar.getTime();
        return getDateTime(date, fmt);
    }
  1. Volley 用法
    郭霖 http://blog.csdn.net/guolin_blog/article/details/17482095

  2. 使用Gson注意事项

使用Gson时注意:
    实体类的成员变量名务必要与Jason串中的属性名一样。
如: 
    {"weatherinfo":{"city":"北京","cityid":"101010100","temp":"18","WD":"东南风","WS":"1级","SD":"17%","WSE":"1","time":"17:05","isRadar":"1","Radar":"JC_RADAR_AZ9010_JB","njd":"暂无实况","qy":"1011","rain":"0"}}

    则对应的实体类为
    public class Weather {
    
        private WeatherInfo weatherinfo;
    
        public WeatherInfo getWeatherinfo() {
            return weatherinfo;
        }
    
        public void setWeatherinfo(WeatherInfo weatherinfo) {
            this.weatherinfo = weatherinfo;
        }
    }


public class WeatherInfo {
    private String city;

    private String temp;

    private String time;

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getTemp() {
        return temp;
    }

    public void setTemp(String temp) {
        this.temp = temp;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }
}

    注意Weather类中的weatherinfo和Jason串中一模一样,否则无法映射。
  1. 闹钟AlarmManager
Intent intent = new Intent(context, SendEmailReceiver.class);

//注意如果设置多个闹钟,requestCode要不一样,否则会覆盖
PendingIntent sender = PendingIntent.getBroadcast(context, requestCode, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

 
 //得到间隔时间
 int interval = 1000 * 60 * 60 * 24;

 Calendar calendar = Calendar.getInstance();
 calendar.set(Calendar.HOUR_OF_DAY, hour);
 calendar.set(Calendar.MINUTE, minute);
 calendar.set(Calendar.SECOND, 0);
 calendar.set(Calendar.MILLISECOND, 0);

 alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
         interval, sender);
image
  1. The same input jar is specified twice 解决办法
打开 proguard.cfg 
在所有的-libraryjars 前插入 # 成 #-libraryjars xxxx.jar

原因分析

原因是build.gradle文件配置了

dependencies {
    compile fileTree(include: '*.jar', dir: 'libs')
}
1
2
3
里面已经添加过jar包,混淆文件proguard.cfg里面又加了句-libraryjars libs/***.jar,将-libraryjars libs/***.jar 前面用#号注释或者直接删掉即可。

sdk 通过 proguard 混淆代码时默认已经将 lib目录中的 jar 都已经添加到打包脚本中,所以不需要再次手动添加。
  1. Gson 的常规用法:

http://www.cnblogs.com/Jude95/p/Mr_Dentist.html

  1. Volley
//使用StringRequest进行POST请求时,参数可以他通过重写getParas()传递
StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
                @Override
                public void onResponse(String s) {
                    Globals.log(Log.ERROR, s);
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError volleyError) {
                    Globals.log(Log.ERROR, volleyError.getMessage());
                }
            }){
                @Override
                protected Map<String, String> getParams() throws AuthFailureError {
                    Map<String, String> map = new HashMap<String, String>();
                    map.put("UserName", account);
                    map.put("PasswordHash", password);
                    return map;
                }
            };
//使用JsonObjectRequest进行POST请求,将参数封装在JSONObject对象中传递给构造函数
Map<String, String> map = new HashMap<String, String>();
map.put("UserName", account);
map.put("PasswordHash", password);
JSONObject jsonObject = new JSONObject(map);

JsonObjectRequest loginRequest = new JsonObjectRequest(Request.Method.POST, url,  jsonObject,
        new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                handleJSONObjectResponse(jsonObject);
            }
        },
        new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError volleyError) {
        Toast.makeText(LoginActivity.this, R.string.internet_request_error, Toast.LENGTH_SHORT).show();
        Globals.log(Log.ERROR, volleyError.getMessage());
    }
}) ;

  1. 代码中获取arrays.xml文件数组
     比如arrays.xml文件中的数组如下:
    <string-array name="select_dialog_items">
        <item>Command one</item>
        <item>Command two</item>
        <item>Command three</item>
        <item>Command four</item>
    </string-array>
        代码中获取该数组资源的具体代码如下:
    String[] items = getResources().getStringArray(R.array.select_dialog_items);

  1. gradle详解
http://www.jianshu.com/p/9df3c3b6067a
  1. 关于BuildConfig类
http://blog.csdn.net/joy_whale/article/details/51858459

可以利用BuildConfig.DEBUG或者BuildConfig.BUILD_TYPE来编写日志类。

  1. 使用第三方SDK时,更新SDK时一定要注意官方的更新文档,接口函数和资源文件的更新里面都会提到。

  2. 重启APP

    Intent intent = getBaseContext().getPackageManager().getLaunchIntentForPackage(getBaseContext().getPackageName());
    PendingIntent restartIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT);
    AlarmManager mgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent); // 1秒钟后重启应用
    System.exit(0);
//查看文件每一行代码的作者  
git blame <file>

//查看文件的提交历史    
git log -p <file>
  1. SQL快速参考

http://www.runoob.com/sql/sql-quickref.html

  1. Object的equals()方法容易抛空指针异常,应使用常量或者确定有值的对象来调用equals().如:
正例:"test".equals(object);
反例:object.equals("test");
  1. 对字符串进行 == 和 equals() 操作时有什么区别?

    == 比较两个字符串的地址,初学者很经常拿来比较其内容,将会导致出现不等的情况。 equals()是String这个类重写的一个方法,平常的类的equals()也仅仅是比较两个变量的地址,而String类的equals()重写后,将依次比较其串中的字符。

52.读取文件

public class BufferedInputFile {
    
    public static String read(String fileName) throws IOException {
        BufferedReader in = new BufferedReader(new FileReader(fileName));
        String s;
        StringBuilder sb = new StringBuilder();
        while ((s = in.readLine()) != null)
            sb.append(s + "\n");
        in.close();
        return sb.toString();
    }

    public static void main(String[] args) throws IOException {
        System.out.print(read("src/file/BufferedInputFile.java"));
    }
}

  1. java中各种基本类型的字节数
image
  1. 实现Serializable的对象在序列化时,不会保存类中的static成员,需要自己实现。

  2. android 6.0(SDK 23)以上获取WRITE_SETTINGS权限

private static final int REQUEST_CODE_WRITE_SETTINGS = 1;
private void requestWriteSettings() { 
    Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
    intent.setData(Uri.parse("package:" + getPackageName())); 
    startActivityForResult(intent, REQUEST_CODE_WRITE_SETTINGS );
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {      
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE_WRITE_SETTINGS) {
        if (Settings.System.canWrite(this)) {
            Log.i(LOGTAG, "onActivityResult write settings granted" );
        }
    }
}

上述代码需要注意的是

使用Action Settings.ACTION_MANAGE_WRITE_SETTINGS启动隐式Intent
使用"package:" + getPackageName()携带App的包名信息
使用Settings.System.canWrite方法检测授权结果
关于WRITE_SETTINGS权限,比较少应用会用到,一般也不建议应用申请,不然Android M也不会设立这道障碍,比危险权限的申请还要复杂。

  1. 注解处理器
  • 由注解处理器生成的类文件在: image
  1. Android 单元测试

  2. 使用volatile的两个必要条件:

  • 对变量的写操作不依赖于当前值。
  • 该变量没有包含在具有其他变量的不变式中。
即变量真正独立于其他变量和自己以前的值

详见 正确使用volatile变量

注意:(适用于Java5及其之后的版本)volatile的读和写建立了一个happens-before关系,类似于申请和释放一个互斥锁。所以java5之后双重校验锁可以正常使用。

Double-checked locking is actually OK as of Java 5 provided that you make the instance reference volatile. So for example, if we needed to pass in a database connection to getInstance(), then this would be OK:

public class MyFactory {
>   private static volatile MyFactory instance;
> 
>   public static MyFactory getInstance(Connection conn)
>        throws IOException {
>     if (instance == null) {
>       synchronized (MyFactory.class) {
>         if (instance == null)
>           instance = new MyFactory(conn);
>       }
>     }
>     return instance;  
>   }
> 
>   private MyFactory(Connection conn) throws IOException {
>     // init factory using the database connection passed in
>   }
> }

Note that this is OK as of Java 5 because the definition of volatile was specifically changed to make it OK. Accessing a volatile variable has the semantics of synchronization as of Java 5. In other words Java 5 ensures that the unsycnrhonized volatile read must happen after the write has taken place, and the reading thread will see the correct values of all fields on MyFactory.

详见Double-checked Locking (DCL) and how to fix it (ctd)

  1. Java集合工具包框架图

    image
    详见 http://www.cnblogs.com/skywang12345/p/3308498.html
  2. 内部类可以访问其外围类的方法和字段,就像自己拥有它们似的。在拥有外部类之前是不可能创建内部类对象的。这时因为内部类对象会暗暗地连接到创建它的外部类对象上。但是如果你创建的是嵌套类(静态内部类),那么它就不需要对外部类对象的引用。

  3. 有return的情况下try catch finally的执行顺序(最有说服力的总结)
    http://blog.csdn.net/kavensu/article/details/8067850

  4. UML类图
    http://www.uml.org.cn/oobject/201104212.asp

  5. ++transient++
    Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。

  6. static字段对每个类来说都只有一份存储空间,而非static字段则是对每个对象有一个存储空间,static方法在不创建任何对象的前提下就可以调用它。

  7. Java_Ant详解
    http://www.cnblogs.com/huozhicheng/archive/2010/04/08/2533199.html

  8. 抽象类可以没有抽象方法,但是如果你的一个类已经声明成了抽象类,即使这个类中没有抽象方法,它也不能再实例化,即不能直接构造一个该类的对象。
    如果一个类中有了一个抽象方法,那么这个类必须声明为抽象类,否则编译通不过。

image
  1. java1.8对接口的扩展
(1)增加default方法。感觉Java的接口也开始融入虚类的属性。对已有的接口,如果想对接口增加一个新方法,那么需要对所有实现该接口的类进行修改。而有了default方法,可以解决该问题。

(2)新增了static函数。
例如,下面接口中定义了一个静态方法 find,该方法可以直接用 StaticFunInterface .find() 来调用。
public interface StaticFunInterface {
    public static int find(){
        return 1;
    }
}
public class TestStaticFun {
    public static void main(String[] args){
        //接口中定义了静态方法 find 直接被调用
        StaticFunInterface.fine();
    }
}
  1. 小数转百分数
import java.text.DecimalFormat;
 
public class Test4 {
 
    public static void main(String[] args) {
        double result=0.051111122111111;
        DecimalFormat df = new DecimalFormat("0.00%");
        String r = df.format(result);
        System.out.println(r);
    }
}
  1. 各种单例模式
    http://www.importnew.com/24272.html

  2. 线程状态
    [图片上传失败...(image-a341af-1534071069706)]

  3. 在线程上调用interrupt()时,中断发生的唯一时刻是在任务要进入到阻塞操作中,或者已经在阻塞操作内部时。

  4. 调用sleep()的时候并没有释放锁,调用yield也是。当一个任务在方法里遇到了对wait()的调用时,线程被挂起,对象锁被释放。只能在同步控制方法或者同步控制块中调用wait(), notify(), notifyAll(),即任务在调用这三个方法前必须拥有对象的锁。

注意:

调用notifyAll时,并不是所有的wait()都会被唤醒,而是同一个对象的wait()才会被唤醒。

  1. 死锁
image
  1. java concurrency join()

The join method allows one thread to wait for the completion of another. If t is a Thread object whose thread is currently executing,

t.join();

causes the current thread to pause execution until t's thread terminates. Overloads of join allow the programmer to specify a waiting period. However, as with sleep, join is dependent on the OS for timing, so you should not assume that join will wait exactly as long as you specify.

Like sleep, join responds to an interrupt by exiting with an InterruptedException.

  1. 导入eclipse项目出现


    image

解决方法:

将Gradle Version改为之前可以运行的版本


image

[图片上传失败...(image-c1f5e2-1534071069706)]

77.Android Studio查找项目中的中文字符:

在全局查找(ctrl+shift+F)中使用以下正则表达式:

^((?!(\*|//)).)+[\u4e00-\u9fa5]

注意需要勾选Regrex选项

image
  1. 如果方法覆盖了超类中的一个方法,子类中的访问级别就不允许低于超类中的访问级别。这样可以确保任何使用超类实例的地方也都可以使用子类的实例。

  2. Activity四种启动模式


    image

attributes in the <uses-sdk> element are overridden by corresponding properties in the build.gradle file. So if you're using Android Studio, you must specify the minSdkVersion and targetSdkVersion values there instead:

android {
  defaultConfig {
    applicationId 'com.example.myapp'

    // Defines the minimum API level required to run the app.
    minSdkVersion 15

    // Specifies the API level used to test the app.
    targetSdkVersion 26

    ...
  }
}
  1. How to write Doc comments?

If you intend for your app to be self-contained and not allow other apps to activate its activities, you don't need any other intent filters. Activities that you don't want to make available to other applications should have no intent filters, and you can start them yourself using explicit intents.

You should not use onPause() to save application or user data, make network calls, or execute database transactions.

84.使用网易邮箱报 535 error authentication failed

image

Once your activity is stopped, the system might destroy the process that contains the activity if the system needs to recovery memory. Even if the system destroys the process while the activity is stopped, the system still retains the state of the View objects (such as text in an EditText widget) in a Bundle (a blob of key-value pairs) and restores them if the user navigates back to the activity.

Coordinating activities

When one activity starts another, they both experience lifecycle transitions. The first activity stops operating and enters the Paused or Stopped state, while the other activity is created. In case these activities share data saved to disc or elsewhere, it's important to understand that the first activity is not completely stopped before the second one is created. Rather, the process of starting the second one overlaps with the process of stopping the first one.

The order of lifecycle callbacks is well defined, particularly when the two activities are in the same process (app) and one is starting the other. Here's the order of operations that occur when Activity A starts Activity B:

  1. Activity A's onPause() method executes.
  2. Activity B's onCreate(), onStart(), and onResume() methods execute in sequence. (Activity B now has user focus.)
  3. Then, if Activity A is no longer visible on screen, its onStop() method executes.

This predictable sequence of lifecycle callbacks allows you to manage the transition of information from one activity to another.

  1. 如果系统因为内存不足杀死了活动所在的进程,onSaveInstanceState()会被自动调用,它的默认实现保存了视图相关的数据,比如EditText中的输入(前提是EditText有设置android:id属性)。如果你想保存一些成员变量的状态,可以在这里保存在Bundle中。onSaveInstanceState()的实现在onPause()之后,在onStop()之前。保存之后,可以在onCreate()或者onRestoreInstance()中恢复这些状态。

The Binder transaction buffer has a limited fixed size, currently 1MB, which is shared by all transactions in progress for the process. Since this limit is at the process level rather than at the per activity level, these transactions include all binder transactions in the app such as onSaveInstanceState, startActivity and any interaction with the system. When the size limit is exceeded, a TransactionTooLargeException is thrown.

For the specific case of savedInstanceState, the amount of data should be kept small because the system process needs to hold on to the provided data for as long as the user can ever navigate back to that activity (even if the activity's process is killed). We recommend that you keep saved state to less than 50k of data.

Note: In Android 7.0 (API level 24) and higher, the system throws a TransactionTooLargeException as a runtime exception. In lower versions of Android, the system only shows a warning in logcat.

  1. SQL join语句
  2. volatile

锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility)。互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的

没有理由在新代码中使用wait和notify,如果你在维护具有wait和notify的代码,务必确保始终是利用标准的模式从while循环内部调用wait。一般情况下,应该优先使用notifyAll。

  1. Java: difference between strong/soft/weak/phantom reference

对于一个正在被反序列化的对象,如果它的类定义了一个readResolve()方法,并且具备正确的声明,那么在反序列化之后,新建对象上的readResolve就会被调用,然后该方法返回的对象引用将被返回,取代新建的对象。在这个特性的绝大多数用法中,指向新建对象的引用不需要再被保留,因此立即成为垃圾回收的对象。

  1. 如果方法覆盖了超类中的一个方法,子类中的访问级别就不允许低于超类中的访问级别。这样可以确保任何使用超类实例的地方也都可以使用子类的实例。

  2. 应该始终尽可能地降低可访问性。除了public static final域之外,公有类都不应该包含public域,并且要确保public static final域所引用的对象都是不可变的,如果引用的是数组、集合等就不应该是public的。

  3. float值使用Float.compare()方法比较大小,double值使用Double.compare()方法比较大小,其他基本类型可以直接使用==来比较。

  4. 不可变对象是线程安全的,它们不要求同步。不可变对象可以被自由的共享,所以不需要任何形式的拷贝,不应该为不可变类提供clone()方法或者拷贝构造器。对于频繁用到的值,为这些值提供public static final域,还可以提供一些静态工厂方法,它们把频繁使用的实例缓存起来,从而当现有实例符合请求的时候,就不必创建新的实例,降低内存占用和垃圾回收的成本。所有基本类型的包装类和BigInteger都有这样的静态工厂方法。

  5. 只有当子类和超类之间确实存在is-a关系时,才应该使用继承,除此之外应该用复合+转发机制的包装类机制,尤其是在存在适当的接口来实现包装类的时候。继承依赖于超类API的具体实现细节,并且会把超类API中的所有缺陷传播到子类中来,而复合则可以设计新的API来隐藏这些缺陷。

  6. 如果允许一个类被继承,比较合理的做法是确保这个类永远不会调用它的任何可覆盖的方法,这样就可以实现能够安全的被子类化的类,覆盖方法将永远不会影响其他方法的行为。通常的做法是:将每个可覆盖方法的代码体移到一个私有的的“辅助方法”中,让可覆盖的方法调用它的私有辅助方法。然后,其他方法如果需要可覆盖方法的功能,就直接调用可覆盖方法的私有辅助方法而不是可覆盖方法本身。

  7. 接口通常是定义允许多个实现类型的最佳方式。如果导出了一个重要接口,就应该坚决考虑提供这个接口的骨架实现类。

  8. 接口应该只被用来定义类型,不应该被用来导出常量。

  9. Java中用函数对象来实现策略模式:首先声明一个接口来表示该策略,然后为每个具体策略声明一个实现了该接口的类。当一个具体策略只被使用一次时,通常使用匿名类来声明和实例化这个具体的策略类。当一个具体策略类是被设计用来重复使用时,它的类通常就要被声明为私有的静态成员类,并通过公有的静态final域导出,其类型为该策略接口。可参阅comparator接口和String类的CASE_INSENSITIVE_ORDER.

  10. 如果成员类的每一个实例都需要指向外围类实例的引用,该成员类就应该声明为非静态的,否则,就应该声明为静态的。

  11. Set<Object>是个参数化类型,表示可以包含任何对象类型的一个集合;Set<?>则是一个通配符类型,表示只能包含某种未知对象类型的一个集合;Set则是原生态类型,它脱离了泛型系统。前两种是安全的,最后一种不安全。不要在新代码中使用原生态类型,除了Set.class和 s instanceof Set两种特殊情形。

  12. 如果类具有从客户端得到的或者返回给客户端的可变组件,类就必须保护性的拷贝这些组件。如果拷贝的成本受到限制,并且类信任它的客户端不会不恰当的修改这些组件,就可以在文档中声明客户端不可以修改这些组件,以此来代替保护性拷贝。

  13. 对于任何需要精确计算的任务,请不要使用float和double,尤其是货币。应该使用BigDecimal或者int,long来代替。

  14. 通常,基本类型优先于装箱基本类型。在装箱基本类型上使用==基本总是错误的,因为它是比较两个引用是否指向同一个对象,而不是比较内部的值。

  15. 如果有合适的接口类型存在,那么对于参数、返回值、变量和域来说,都应该使用接口类型来声明。只有需要使用具体的实现类中的方法时,才应该用具体类型。

  16. 嵌套Fragment注意事项

注意嵌套Fragment时,只能动态添加内层Fragment,使用宿主Fragment的getChildFragmentManager()函数,不要在xml布局文件中使用<fragment>标签.

相关文章

网友评论

      本文标题:Android 学习笔记

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