安卓基础知识疑难点总结

  * 重写 Override
      
      从父类继承的方法,
      不满足子类需要,
      可以在子类中重新编写这个方法
      
      *)重写一个方法时,
        可以用 super.xxx()
        调用父类同一个方法的代码

  * 创建子类对象
      
      1)先创建父类对象,执行父类构造方法
      2)再创建子类对象,执行子类构造方法
      *)两个对象绑定在一起,
        整体作为一个子类对象
      
      *)调用成员时,
        先找子类,再找父类
* 创建子类对象时,先执行父类构造方法
      
      *)默认执行父类无参构造方法
          
          super()
      
      *)手动调用父类有参构造
          
          super(参数)
super
  ------------------------------------
    * 两种用法
    
    * 重写时,调用父类同一个方法
          
          public String toString() {
              ...
              super.toString()
              ...
          }
    
    * 手动调用父类构造方法
          
          super(参数)
          
          *) 必须是首行代码
多态
============================================
  * 作用: 一致的类型
 
  * 类型转换
      
      *)向上转型
          
          子类对象,转换成父类类型
      
      *)向下转型
          
          已经转为父类型的子类对象,
          再转回成子类型
  * instanceof
      
      判断一个对象的类型
      对真实类型,及其父类型判断,都得到true
      
      Shape s = new Line();
      
      s instanceof Line   true
      s instanceof Shape  true
  * 抽象类不能创建实例
    只能创建它子类的实例
  * 包含抽象方法的类,必须是抽象类
    抽象类中,不一定包含抽象方法
==================================
final
========================================
  * 修饰变量、方法、类
 
  变量
  -----------------------------------
    * 变量的值不可变,成为“常量”
        
        *)基本类型的值,是值本身不可变
        *)引用类型的值,是引用的地址不可变
        
        final int a = 10;
        a = 11;//错
        
        -----
        
        final Point a = new Point(3, 4);
        a.x = 30;//对
        
        a = new Point(1,5);//错
        a = null;//错

 
  final 方法
  ----------------------------------------
    * 方法不能被子类重写
 
  final 类
  ----------------------------------------
    * 不能被继承
============================================


Android中的UI线程模型
--------------------------
UI:User Interface
在Android系统中,主线程是用于初始化界面、响应用户在界面上的操作等等的,所以,主线程也叫做UI线程。
UI线程执行时间过长,则可能导致ANR!如果是在Activity中,则超过5s就可能出现ANR,如果是在BroadcastReceiver中,则超过10s就可能出现ANR。
对于开发者而言,只要是消耗时间可能比较长的操作,都应该规避处理。
解决ANR问题的根本方法:把耗时操作放在子线程中运行!


关于在子线程中更新UI
--------------------------
小结:不允许在子线程中直接更新UI,否则应用程序将崩溃
官方解释:只能创建UI控件的线程,才可以操作这些UI控件,而创建UI控件的过程都是由主线程/UI线程完成的
源码解释:只有拥有ViewRoot的线程才可以操作UI控件,主线程默认即有ViewRoot,而线程通常没有ViewRoot。
解决方案:当需要在子线程中更新UI时,调用runOnUiThread()方法即可。



进度条
========================================
ProgressBar:进度条
--------------------------
【属性】
1. style -> 进度条的样式
2. android:max -> 进度的最大值
3. android:progress -> 当前进度
【方法】
void setMax(int)
int getMax()
void setProgress(int)
int getProgress()


=========================================
ImageView是用于显示图片的控件属性的用法与imagebutton相同
属性:
android:src -> 需要显示的图片的来源,取值通常为 @drawable/???
android:contentDescription -> 使用文字对图片进行描述,如果不想设置,可以取值为 @null
android:scaleType -> 图片的缩放模式,当图片的尺寸与ImageView的尺寸不符时有效,取值为枚举类型  



================================
Ctrl + 2, R -> 批量重命名,先把光标放在需要重命名的变量位置(不用选中),然后按Ctrl+2,然后马上按住R可以对其批量重命名。

===============================
请详细描述“封装”的概念。
--------------------------------
封装是面向对象的三大特征(封装、继承、多态)之一。
封装的具体表现是“装”与“封”。
装:将一组相关的属性和方法编写在一个类中。
封:使用相对比较严格的访问权限修饰各个属性,并提供相对宽松的set和get方法。

===============================
访问权限修饰符:用于修饰类的成员,当修饰普通的类时,只能使用public或者默认权限(即没有修饰符)。
public:任意访问
protected:同包的各个类之间,子类可以访问
(空):同包的各个类之间可以访问
private:仅类的内部可以访问
}
==============================
package cn.tedu.tab_menu_2;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends Activity {
    private Button btnDeal;
    private Button btnNearby;
    private Button btnMy;
    private Button btnMore;
    private TextView tvContent = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        btnDeal = (Button) findViewById(R.id.btn_tab_menu_deal);
        btnNearby = (Button) findViewById(R.id.btn_tab_menu_nearby);
        btnMy = (Button) findViewById(R.id.btn_tab_menu_my);
        btnMore = (Button) findViewById(R.id.btn_tab_menu_more);
        tvContent = (TextView) findViewById(R.id.tv_content);
        
        InnerOnClickListener listener = new InnerOnClickListener();
        btnDeal.setOnClickListener(listener);
        btnNearby.setOnClickListener(listener);
        btnMy.setOnClickListener(listener);
        btnMore.setOnClickListener(listener);
        
        // 默认选中“团购”
        selectButton(R.id.btn_tab_menu_deal);
    }
    
    // 当前显示的界面匹配的按钮的ID
    // current -> 当前的
    private int currentButtonId = R.id.btn_tab_menu_deal;
    
    private void selectButton(int which) {
        // 判断本次点击的按钮的ID与此前记录的ID是否相同,如果相同,不执行任何代码,如果不相同,则执行以下代码
        if(currentButtonId != which) {
            // 取消所有按钮的选中
            btnDeal.setSelected(false);
            btnNearby.setSelected(false);
            btnMy.setSelected(false);
            btnMore.setSelected(false);
            
            // 记录当前点击的按钮的ID
            currentButtonId = which;
                   curtentButtonId =which
            // 确定点击的按钮控件
            Button btn = (Button) findViewById(which);
                        Button btn=findViewById (which);
            // 获取按钮上的文字
String text=btn.getText().toString();
            String text = btn.getText().toString();
            // 设置正文文字
tvContent.setText(text);
            tvContent.setText(text);
            // 选中按钮
btn.setSeleted(true);
            btn.setSelected(true);
        }
    }
    
    private class InnerOnClickListener implements OnClickListener {

        @Override
        public void onClick(View v) {
            selectButton(v.getId());
            
//            switch (v.getId()) {
//            case R.id.btn_tab_menu_deal:
//                selectButton(R.id.btn_tab_menu_deal);
//                break;
//                
//            case R.id.btn_tab_menu_nearby:
//                selectButton(R.id.btn_tab_menu_nearby);
//                break;
//                
//            case R.id.btn_tab_menu_my:
//                selectButton(R.id.btn_tab_menu_my);
//                break;
//                
//            case R.id.btn_tab_menu_more:
//                selectButton(R.id.btn_tab_menu_more);
//                break;
//            }
        }
        
    }


}
========================================

方法的参数:参数是当执行方法时所需要的条件。
public class Sample {
  void sum(int x, int y) {
 
  }
}
========================================
如果开发者显式的声明了构造方法,则编译器不会再自动添加构造方法。
构造方法可以用于创建对象时直接指定对象的某些属性值,例如没有构造方法时:
public class Person {
  public String name;
  public int age;
}
public class Test {
  public static void main(String[] args) {
    Person p = new Person();
    p.name = "Jack";
    p.age = 18;
  }
}
如果指定了构造方法:
public class Person {
  public String name;
  public int age;
 
  public Person(String personName, int personAge) {
    name = personName;
    age = personAge;
  }
}
public class Test {
  public static void main(String[] args) {
    Person p = new Person("Jack", 18);
  }
}
构造方法也可以重载,例如:
public class Person {
  public String name;
  public int age;
 
  public Person() {
  }
 
  public Person(String personName, int personAge) {
    name = personName;
    age = personAge;
  }
}
====================================================================================
3. this、super关键字
this表示当前类的对象,super表示当前类的父类的对象。
public class Person extends Object {
  public String name;
 
  public Person() {
    this("unknown"); // 调用自身的另一个构造方法
  }
 
  public Person(String name) {
    super(); // 调用父类的构造方法
    this.name = name;
  }
 
  public String toString() {
    return null;
  }
 
  public void test1() {
    super.toString();
  }
 
  public void test2() {
    toString();
  }
 
}
public class Test {
  public static void main(String[] args) {
    Person jack = new Person("Jack");
    jack.name = "Jackson";
    // Person.name = "???"; // 普通属性不可以这样调用
    Person mike = new Person("Mike");
  }
}
=========================================================================================
4. 内部类
内部类就是声明在其它类的内部的类,主要有:
1) 成员内部类:以类的成员的形式出现的内部类,例如:
public class Sample {
  public void run() {
    InnerClass ic = new InnerClass();
  }
 
  public class InnerClass {
    System.out.println(x);
  }
 
  public int x;
}
成员内部类可以使用任何访问权限修饰符。
内部类可以访问外部类的任意成员,包括私有的。
在没有创建外部类的对象之前,不可以直接创建内部类的对象。

2) 局部内部类:定义在方法的内部的内部类。
public class Sample {
  public z = 10;
 
  public void run() {
    int x = 10;
    final int y = 10;
    
    class InnerClass {
      void test() {
        // System.out.println(x); // 错误
        System.out.println(y); // 正确
        System.out.println(z); // 正确
      }
    }
    
    InnerClass ic = new InnerClass();
  }
}
局部内部类不可以使用任何访问权限修饰符。
使用局部内部类时,需要注意代码的先后顺序。
在局部内部类中,不可以直接访问局部变量,如果一定需要访问,可以使用final修饰该局部变量,或者将局部变量声明为全局变量(类的属性)。

3) 静态成员内部类:静态内部类是使用static修饰的成员内部类,例如:
public class Sample {
  public static int x = 10;
 
  public static class InnerClass {
    public void run() {
      System.out.println(x);
    }
  }
}
静态内部类不可以访问外部类中非静态的成员。
静态内部类可以直接创建对象,而不需要依赖于外部类的对象。

4) 匿名内部类:直接创建已知的类的子类对象,或者已知的接口的实现类对象,而创建时,并不体现子类/实现类的名称,即创建出来的对象的类名是未知的,例如:
public class Sample {
  protected void onCreate() {
    new OnClickListener() {
      @Override
      public void onClick(View v) {
      }
    };
  }
}
=============================================================================nieme
匿名内部类表现为,没有类的声明语法,直接创建已知类的子类的对象或者已知接口的实现类对象
public class OuterClass{
   public int id=new Object(){
       public int calculate(){
      return hashCode()*100;
       }
   }
   public void run(){
      new Object(){
        public void helloworld(){
            system.out.println("hello!world!!!")
        }
      }.helloworld();
   }
}
================================================================
Logcat日志级别
---------------------------------------
v -> verbose -> 观察 -> 黑色
d -> debug -> 调试 -> 绿色
i -> info -> 信息 -> 蓝色
w -> warn -> 警告 -> 橙色
e -> error -> 错误 -> 红色
=====================================================================

Object中的常用方法:
>> String toString() -> 通常用于显示对象的属性值及相关信息,在输出对象时,将默认调用该方法。
>> boolean equals(Object object) -> 判断2个对象是否是同一个对象。
>> int hashCode() -> 获取对象的hash码,没有被重写过的hashCode()的返回值,可以用于判断对象是否相等,即hash码相同,则是同一个对象,反之,则不是同一个对象。
>> Class<?> getClass() -> 获取对象所归属的类的信息
========================================================================
在重写时,必须与父类的方法的返回值、方法名、参数列表保持一致。
在重写时,不可以使用比父类的方法更严格的访问权限,例如父类的方法使用protected修饰,则在子类中重写时,可以使用protected、public,不可以使用private。
在重写时,不可以抛出比父类的方法更多,或者范围更大的异常,例如父类的方法抛出FileNotFoundException,则在子类中,如果也抛出了FileNotFoundException,是正确的,但是,在此基础上,抛出了其它非RuntimeException则是错误的,因为抛出了更多的异常,或者在子类中,不抛出FileNotFoundException,却抛出IOException也是错误的,因为抛出了范围更大的异常。简言之:子类重写时,抛出的异常相比父类只能少不能多,不能抛出父类中没有抛出的非RuntimeException。
===========================================================================
1. 请详细描述“多态”的概念
多态:编译期与运行期为不同的形态,例如:
Animal a = new Dog();
当应用了多态后,对象只能访问声明的类型(父类)中已经声明的属性和方法,而子类中新定义的属性和方法是不可以访问的,如果需要访问子类的属性和方法,则需要向下转型,且向下转型之前应该检查对象的数据类型是否匹配。
当应用了多态后,对象调用的方法,会优先调用子类重写后的方法。
多态的应用方式:数组多态、参数多态、返回值多态……只要是声明的类型是父级类别,当需要值时,都可以使用子级类型创建的对象。

public class Animal {
  public void run() {}
}
public class Dog extends Animal {
  public void run() {}
 
  public void bite() {}
}
public class Test {
  public static void main(String[] args) {
    Animal a = new Dog();
    a.run();
    // a.bite(); // 错误
    if(a instanceof Dog) {
      Dog d = (Dog) a;
      d.bite();
    }
    // Cat c = (Cat) a; // 错误
  }
}
===========================================================================
===========================================================================
创建新的Activity需要自定义类继承自android.app.Activity类,并且根据业务的需要,重写指定的方法,例如onCreate()方法等。然后一定要记得先注册!!当需要销毁所有Activity时,遍历List集合,调用每一个Activity对象的finish()方法
===========================================================================
3. 请详细描述final关键字的意义
final修饰类不允许被继承
final修饰的方法不可以被重写
final修饰的变量不允许被二次赋值
=======================================================================

如何一次性销毁当前应用程序打开的所有Activity
---------------------------------
创建static List<Activity>用于保存所有打开的Activity
在每一个Activity的onCreate()方法中,将当前Activity对象添加到List集合中
在每一个Activity的onDestroy()方法中,将当前Activity对象从List集合中移除
当需要销毁所有Activity时,遍历List集合,调用每一个Activity对象的finish()方法
=========================================================================

Activity的启动模式
---------------------------------
任务栈:系统使用任务栈记录当前应用程序已经激活的Activity组件,所以,当用户按下Back键时,系统可以根据任务栈中的记录,显示上一次显示的界面。
压栈:当有新的Activity被显示时,则新的Activity执行压栈操作,该Activity将处于栈顶位置,显示在前台,而栈内原有的Activity将依次处于栈次偏下方的位置。
弹栈:当栈顶的Activity出栈(被销毁)时,栈内其它的Activity将弹栈,且原来最贴近栈顶的Activity将获得栈顶位置,显示在前台。
Activity的启动模式将直接影响任务栈中的记录。
Activity的启动模式是在AndroidManifest.xml中为<activity>节点配置android:launchMode属性实现的,该属性的取值有:
1. standard:标准 -> 默认值,每次激活该Activity时,都会创建新的对象,并压栈
2. singleTop:栈顶唯一 -> 当Activity处于栈顶位置时唯一,即在栈顶位置时激活该Activity并不会创建新的Activity对象,反之,不在栈顶时则与standard相同
3. singleTask:任务栈内唯一 -> 当栈内没有该Activity时,激活将创建新的Activity并压栈,当栈内已经存在该Activity时,激活将不再创建新的Activity,且栈内会弹栈,在栈内位于该Activity上方的其它Activity均被强制出栈。
4. singleInstance:实例唯一 -> 该Activity的实例最多只存在1个,且该Activity独自占有1个任务栈。
=========================================================================

2. 请详细描述“接口”的概念
  接口的组成结构与类基本一致。
  接口中的所有成员都是公有(public)的。
  接口中的所有属性都是静态常量(static final)。
  接口中的所有方法都是抽象的(abstract)
  以下2种语法是完全等效的:
  public interface USB {
    String NAME = "usb-device";
    void read();
    void write();
  }
  public interface USB {
    public static final String NAME = "usb-device";
    public abstract void read();
    public abstract void write();
====================================================================
在Activity或Service中,调用getApplication()方法即可获取Application对象。
注意:不要自行创建Application对象!凡是自行创建的系统组件类的对象,均不会由系统进行维护,即系统并不会对这些对象进行管理,亦不会调用这些对象的任何方法。
======================================================================


你可能感兴趣的:(安卓基础知识疑难点总结)