Android 虚拟机运行缓慢的解决方法

1. 直接在手机上跑,最简单最快。

2. 创建虚拟机时,选择与自己计算机 CPU 类型相同的处理器类型。如果是 intel x86 系列,那么在选择虚拟机的 System Image 时也选择 x86 类型的 ABI(Application Binary Interface)。另外,如果计算机使用的是 intel 处理器,可以下载安装 HAXM 进行加速。下载地址:https://software.intel.com/en-us/android/articles/intel-hardware-accelerated-execution-manager

3.创建虚拟机时,启用 Snapshot.

4.可以试一试 GenyMotion 的虚拟机,个人使用是免费的。速度相对自带的会快不少。

Back to Android

Start to read Head First Android Development.

Issues about the xml attribute android:ems

Chapter 3

<EditText
        android:id="@+id/message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/send"
        android:layout_below="@+id/send"
        android:layout_marginTop="18dp"
        android:ems="10"/>

I get a little confused about what is meant by ems. And found the answer below.

android:ems or setEms(n) sets the width of a TextView to fit a text of n ‘M’ letters regardless of the actual text extension and text size. See wikipedia Em unit

but only when the layout_width is set to "wrap_content". Other layout_width values override the ems width setting.

Adding an android:textSize attribute determines the physical width of the view to the textSize * length of a text of n ‘M’s set above.

Issues about the frament onAttach() method.

When tested the code showed in Chapter 7,

public void onAttach(Activity activity) {
        super.onAttach(activity);
        Log.d("aaaabbb", "aaaaaa");
        this.listListener = (WorkoutListListener)activity;
    }

Android Studio indicated that this method is deprecated, and suggest to use the code

onAttach(Context context)

instead.

However, after I changed the code

@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
this.listener = (WorkoutListListener)activity;
}

to

    @Override
    public void onAttach(Context context) {
        Log.d("=======", "onAttach");
        super.onAttach(context);
        this.listListener = (WorkoutListListener) context;
    }

it occurred to me that the onAttach(Context context) didn’t even be called when running the app on virtual device with an API level of 21. Seem that many people also meet the problem.(eg, see here, and here) And when testing the same code on devices running an API level of 23, it performs perfectly. TL; DR: when the API level is less than 23, override onAttach(Activity). When the API level is equal or bigger than 23, then override onAttach(Context).

Marks on Fragment Life Circle

onCreate():

The onCreate() method in a Fragment is called after the Activity‘s onAttachFragment() but before that Fragment‘s onCreateView().
In this method, you can assign variables, get Intent extras, and anything else that doesn’t involve the View hierarchy (i.e. non-graphical initialisations). This is because this method can be called when the Activity‘s onCreate() is not finished, and so trying to access the View hierarchy here may result in a crash.

onCreateView():

After the onCreate() is called (in the Fragment), the Fragment‘s onCreateView() is called. You can assign your View variables and do any graphical initialisations. You are expected to return a View to this method, and this is the main UI view, but if your Fragment does not use any layouts or graphics, you can return null.

onActivityCreated():

As the name states, this is called after the Activity‘s onCreate() has completed. It is called afteronCreateView(), and is mainly used for final initialisations (for example, modifying UI elements).


To sum up…
… they are all called in the Fragment but are called at different times.
The onCreate() is called first, for doing any non-graphical initialisations. Next, you can assign and declare any View variables you want to use in onCreateView(). Afterwards, use onActivityCreated() to do any final initialisations you want to do once everything has completed.

reference from http://stackoverflow.com/questions/28929637/difference-and-uses-of-oncreate-oncreateview-and-onactivitycreated-in-fra

Found a bug in Android Studio.

In Chapter 9, the book tells us how to add action bars and add action items to the bar. Since I use an API level of 23 to compile the project, I removed the dependency on appCompact-v7, and modified the showAsAction attribute of the item nodes in menu resource file. As is said, if the project has no dependency on v7 appcompact library, showAsAction must be prefixed with

android:

, not

app:

. And can omit the attribute

xmlns:app="http://schemas.android.com/apk/res-auto"

So the final version of my menu_main.xml becomes:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="com.hfad.bitsandpizzas.MainActivity">

    <item
        android:id="@+id/action_create_order"
        android:title="@string/action_create_order"
        android:icon="@drawable/ic_action_new_event"
        android:orderInCategory="1"
        android:showAsAction="ifRoom" />

    <item
        android:id="@+id/action_settings"
        android:orderInCategory="100"
        android:title="@string/action_settings"
        android:showAsAction="never" />
</menu>

And then Android Studio code assist showed en error on android:showAsAction

Should use app:showAsAction with the appcompat library with xmlns:app="http://schemas.android.com/apk/res-auto"less… (Ctrl+F1)

When using the appcompat library, menu resources should refer to the showAsAction in the app: namespace, not the android: namespace.

Similarly, when not using the appcompat library, you should be using the android:showAsAction attribute.

It really disappointed me at first, and I searched on the Internet for several hours to find out how could I make this a correct one. Finally I decided to try compile the module regardless of the error. Surprisingly, no error occurs during the build, and when I install the app and run on the android device, it performs perfect. This morning, I searched the Internet again in order to find some suggestion. And I found people here who have the same problem as me.

This really cost me a lot of time. I should learn from the lesson not to always believe the IDE. The thing that really matters is the final result, believe what you’ve learn and always try the ideas.

Another android studio bug

There’s already an issue.

Cannot see files inside /data via DDMS

It seems that /data has a more strict privilege than the common directories. The solution is to use an Android application called Root Explorer to set the /data directory’s privilege to 777.

What do three dots in parameters mean

When studying the Chapter 12, there’s such a code block:

protected Boolean doInBackground(Integer... drinks) {
    // some codes
}

The three dots means arbitrary arguments of the specific type.

一本正经的胡说八道

请原谅我真的不知道这个标题用英文应该怎么说。看到 13 章 Log 部分有个 Log.wft(),书中有段旁注:

There’s also a Log.wtf() method you can use to report exceptions that should never happen. According to the Android documentation, wtf means “What a terrible Failure”. We know it means “Welcome to Fiskidagurinn”, which refers to  the Great Fish Day festival held annually in Dalvik, Iceland. Android Developers can often be heard to say “My AVD just took 8 minutes to boot up. WTF??” as
a tribute to the small town that gave its name to the standard Android executable bytecode format.

想到之前还被书中特意放的一段错误代码耍了好久(Fragment 中的 onClick 绑定),我已经决定有机会要买个 Head First 大全集来拜读了,这种文风实在是 1024 个赞。

为何 JAVA 中子类异常类型不能比父类异常类型的范围更大

如果一个方法声明了会抛错,子类中重写的方法只能声明抛出同样的异常或者是抛出该异常的子类。

class A {
   public void foo() throws IOException {..}
}

class B extends A {
   @Override
   public void foo() throws SocketException {..} // 允许

   @Override
   public void foo() throws SQLException {..} // 不允许
}

SocketException 继承了 IOException, 但是 SQLException 不继承.

这样的规定是出于多态的考虑。

A a = new B();
try {
    a.foo();
} catch (IOException ex) {
    // forced to catch this by the compiler
}

如果 B 要抛出 SQLException,编译器并不能强制让你去捕获该异常,因为此时正使用 B 的父类 A。

The rule that you need to be able to refer to objects by their superclass is the Liskov Substitution Principle.

原帖地址:http://stackoverflow.com/questions/5875414/why-cant-overriding-methods-throw-exceptions-broader-than-the-overriden-method

JAVA 中 LinkedList 使用 iterator 遍历的效率问题

看视频中介绍 java.util.LinkedList 提到使用 iterator 对LinkedList 进行遍历时效率高。一开始没想通,毕竟 LinkedList 本质上就是一个链表,那么无论如何,想取在位置 i 上的链表元素,肯定要从头遍历过去,那么 for 从 1 到 i 和使用 iterator 从 1 到 i 应该并没有什么效率上的差别才对。一开始总以为是 iterator 用了什么黑科技,跑去看了 iterator 的源码,就是一个cursor 从头开始的遍历,理论上应该是一样才对。然而结果确实是 iterator 的效率要高很多。最后试着从 for 循环遍历的角度去看,发现了问题所在。

在 for 循环的遍历中,取到具体某个元素要调用 LinkedList 的 get() 方法,而在 get() 实现时,其实又利用 index 去做了一次 for 循环。相当于 for 循环的时间复杂度为

(1)   \begin{equation*}O(n^2)\end{equation*}

,而 iterator 的时间复杂度是

(2)   \begin{equation*}O(n)\end{equation*}

,因此说 iterator 对 LinkedList 的遍历有着更高的效率。

java 中 == 和 equal() 的区别

1.     Java == vs equals() confusion

Q:

I wanted to clarify if I understand this correctly:

== -> is a reference comparison, i.e. both objects point to the same memory location
.equals() -> evaluates to the comparison of values in the objects
Am I correct in my understanding ?

A:

In general, the answer to your question is “yes”, but…

equals will only compare what it is written to compare, no more, no less.
if a class does not override the equals method, then it defaults to the equals(Object o) method of the closest parent class that has overridden this method.
If no parent classes have provided an override, then it defaults to the method from the ultimate parent class, Object, and so you’re left with the Object#equals(Object o) method. Per the Object API this is the same as ==; that is, it returns true if and only if both variables refer to the same object, if their references are one and the same. Thus you will be testing for object equality and not functional equality.
Always remember to override hashCode if you override equals so as not to “break the contract”. As per the API, the result returned from the hashCode() method for two objects must be the same if their equals methods shows that they are equivalent. The converse is not necessarily true.

Android 学习笔记 – 第四天

ListView

Adapter 的概念。这里可以参考 Head First Design Patterns 的相关部分进行理解。

然后遇到了个蛋疼的监听器报错事件不存在的问题。。。返回去先看 java 好了。。。

 

Head First JAVA

布局。FlowLayout 从左到右,从上到下依次摆放组件,在空间不足时,自动换行到下一行,默认的代码测试没有效果,通过 setPreferredSize(new Dimension(int width, int height)) 来控制 Jpanel 的大小后,可以看到确实换行了。

Android 学习笔记 – 第三天

UI 界面

HelloWorld 中的 TextView ,使用 android:gravity 属性设置居中属性无效,设置后仍然是靠左显示(布局为 LinearLayout, orientation=”vertical” )。

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:text="Hello World!" />

这是由于在 android:layout_width 中设置的属性为 wrap_content,这样显示的时候,TextView 的宽度应该是正好包裹着 Text 的。所以导致了这时候不论是何种 gravity ,看起来都一样。将 layout_width 属性修改为 match_parent 后,则默认宽度匹配父级组件,这样就能看到效果了。

<TextView
    android:layout_width="<strong>match_parent</strong>"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:text="Hello World!" />

android:textSize=”24sp”. 这里涉及到几个单位的问题。官网文档链接。还可以参考 StackOverflow 的一个答案,里面给出了具体的转换表。一般推荐字体使用 sp 单位,像素使用 dp 单位,便于各种不同分辨率的屏幕的适配。

ImageView

按照 demo 做到 imageView.setImageResource(R.drawable.picname) 这一步时,编译报错 no marked region found along edge,这个是由于拷贝过去的外部图片文件夹中带有一张 more.9.png 图片,.9.png 是 android 平台中的一种特殊格式文件,具体可以参考这篇文章。这个报错是由于使用的这张 .9.png 图片中缺少了定位区域导致的。 Android Studio 中已经集成了 .9.png 图片编辑工具,在 AS 中双击打开目标图片文件,加黑边编辑后,重新编译,报错 can’t have more than one marked region along edge,这是由于在编辑时候侧边加了两段黑色标记区域,再次修改后,编译正常。

FrameLayout 后面加载的组件会覆盖在前面加载的组件上。

从头写 layout 的 xml 文件,layout 类型后面总是跟着

xmlns:android="http://schemas.android.com/apk/res/android

,查了一下,这个 URI 主要和 java 中的 package 的概念差不多,主要是为了标识 xml 文件,具体可以看下面的这一段说明(源地址):

In XML, xmlns declares a Namespace. In fact, when you do:

<LinearLayout android:id>
</LinearLayout>

Instead of calling android:id, the xml will use http://schemas.android.com/apk/res/android:id to be unique. Generally this page doesn’t exist (it’s a URI, not a URL), but sometimes it is a URL that explains the used namespace.

The namespace has pretty much the same uses as the package name in a Java application.

Here is an explanation.

Uniform Resource Identifier (URI)

A Uniform Resource Identifier (URI) is a string of characters which identifies an Internet Resource.

The most common URI is the Uniform Resource Locator (URL) which identifies an Internet domain address. Another, not so common type of URI is the Universal Resource Name (URN).

In our examples we will only use URLs.

layout_gravity 和 gravity 的区别:

gravity 这个英文单词是重心的意思,在这里就表示停靠位置的意思(参考文章)。

android:layout_gravity 和 android:gravity 的区别

从名字上可以看到,android:gravity是对元素本身说的,元素本身的文本显示在什么地方靠着换个属性设置,不过不设置默认是在左侧的。

android:layout_gravity是相对与它的父元素说的,说明元素显示在父元素的什么位置。

比如说button: android:layout_gravity 表示按钮在界面上的位置。 android:gravity表示button上的字在button上的位置。

XML 使用 include 标签引入另一个 xml 文件的布局。测试 include 要放在控件位置前,放控件后并不会起效果。通过引入自定义控件也是一样,放前面才有效。若要绑定响应事件等,更适合使用自定义控件的方式。

Android 对于 XML 文件采用 PULL 方式进行解析。具体分析可以参考这篇文章

自定义控件部分的核心内容主要是 LayoutInflater 的使用,郭林在博客写过一篇很好的分析文章,介绍得很详细(链接地址)。先通过

 LayoutInflater layoutInflater = LayoutInflater.from(Context)

来获取到 LayoutInflater 实例。然后调用它的 inflate() 方法来加载布局。

layoutInflater.inflate(resourceId, root)

第一个参数是要加载的布局 ID, 第二个是给该布局的外面再嵌套一层父布局。若不需要父布局,可以传 null。

Android 学习笔记 – 第二天

从 Intent 部分开始。

Intent 分为显式 Intent 和隐式 Intent。

显式 Intent 重载 new Intent(Context packageContext, Class<?> cls) 构造函数(例子中重写 onClick() 方法),new Intent 后通过 startActivity() 方法启动目标活动。

隐式 Intent 指明的是 action 和 category 等信息,由系统分析后找出匹配的 Activity 来调用。在 AndroidManifest.xml 中,配置 <Activity> 标签下的 <intent-filter>,指定对应 Activity 所相应的 action 和 category。然后 Intent intent = new Intent(“%ACTION%”) ,intent.addCategory() 方法添加 category。 这里 category 里面写的路径貌似并没有严格规定,测试了一下只要和之前在 intent-filter 中对应的 category 一致即可调用。注意 <action> 和 <category> 需要同时匹配。但是 android.intent.category.DEFAULT 是默认的 category,调用 activity 时会自动将该 category 添加到 Intent 中。每个 Intent 只能指定一个 action,但 category 可以有多个。添加多个时会去 AndroidManifest.xml 中去找对应匹配的 Activity,全部条件满足(包含于) Activity 中定义的 action 和 category 属性,就能够成功调用特定的 Activity。

隐式 Intent 既可启动程序内 Activity,亦可启动其他程序的 Activity,从而可以实现多个应用程序的功能共享。例如调用系统浏览器,调用系统拨号盘等。

除了启动 Activity 外,还可以在启动 Activity 时传递数据

通过重载 putExtra() 方法向下一个活动传递数据,intent.putExtra(“dataname”, data) ,然后在下一个 Activity 中Intent intent = getIntent() ,String data = intent.getStringExtra(“dataname”)。这里遇到个问题,在虚拟机中跑时,Log.d(String, data) 在 LogCat 中能正常打印,但是在实体机上跑时,LogCat 中一直看不到信息。查阅资料后,通过以下方式解决:在拨号盘输入 *#*#2846579#*#* ,进入工程菜单,选择后台设置并将里面日志相关的部分功能打开,即可显示(顺便吐槽下华为手机真是渣渣!)。

返回数据给上一个活动。