手機安全衛士(七)----- 接着回顧之前的代碼

緊接着上一篇博客,接着複習Android的知識點。一個暑假的時間自己在學車,即使每天都看了一點點知識,但是效率不高,現在需要在圖書館裏給他補起來!

第五個知識點:如何利用Handle處理

在默認情況下,Android所有的操作都在主線程中進行,對一些耗時的操作,必須開啓一個子線程來處理。這就需要用到Handle,通俗點來說,就是在子線程中獲取數據,數據獲取完之後,handle發送“數據已經獲得的消息”,然後在主線程中把這些數據在組件中展示出來。

下面是具體的用法(類似與一種框架):

首先開啓一個子線程,像是從數據庫中取數據,進行網絡需求下載數據等等都需要進行開啓子線程,

子線程中存在多種消息(多種情況)

 new Thread(){
            @Override
            public void run() {
                 msg = Message.obtain();
                 msg.what = "0101"
                 handler.sendMessage(msg);
       
            }
        }.start();
private Handler handler = new Handler(){
        public void handleMessage(Message msg){
            switch (msg.what){
                case 0101:
                    //執行相應的操作
                    break;
                case 0102:
                    //執行相應的操作
                    break;
                default:
        }
    }
}

子線程中只存在一種消息:

new Thread(){
            @Override
            public void run() {
         
                handler.sendEmptyMessage(0);
            }
 }.start();
 private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            lv_contact_items.setAdapter(new ContactAdapter());

        }
    };

Handle的使用框架就是上面的兩種方式。

第六個知識點:SQLlite的使用

使用這個知識點的時候,我是真正的感覺到了書上的知識畢竟是書上的,自己寫的代碼是自己的寫的,這還得從實踐中得到真知啊!

三步走使用sqlite

第一步首先建立DBHelper,建造數據庫:

public class BlackNumberDBHelper extends SQLiteOpenHelper {
    public BlackNumberDBHelper(Context context) {
        super(context,"blacknumber.db",null,1);
    }

    /**
     * 創建一個數據庫表
     * @param db
     * 包含三個字段  id  phonenumber  model
     * model 0 全部攔截   1 電話攔截  2 短信攔截
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table number1 (id Integer primary key AUTOINCREMENT,phonenumber varchar(20),model varchar(2) )");

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

構建這個類,首先要繼承SQLiteOpenHelper類,然後最重要的就是構造方法,使用父類的構造方法,傳入一個上下文參數,第二個是數據庫名稱,其他兩個不重要,照着寫就行。

第二個方法是構建一張表,這就能用到之前學的數據庫的知識了,注意點就是上面的表名就是number1,在編寫第二步類的時候,要與這個表名保持一致纔行!!!

然後就可以執行第二步了;

第二步:寫BDDao

我覺得這個類中最主要就是構造方法,忽然覺得有一種豁然開朗的感覺,非常的舒服!



public class BlackNumberDao {
    private BlackNumberDBHelper db;
    private String tablename = "number1";

    //寫在構造器中   只要對象new 出來   數據庫就會自動創建
    public BlackNumberDao(Context context) {
        db = new BlackNumberDBHelper(context);
    }



    public List<BlackNumberInfo> QueryAll(){

        SQLiteDatabase readableDatabase = db.getReadableDatabase();
        Cursor query = readableDatabase.query(tablename, null, null, null, null, null, null);
        while (query.moveToNext()){   
            String phone = query.getString(1);
            blackNumberInfo.setPhonenumber(phone);
            String model = query.getString(2);      
        }
        query.close();
        readableDatabase.close();
        return list;

    }



    /**
     * 往數據庫中添加數據
     *
     * @param phone 電話
     * @param model 攔截模式
     */
    public Boolean Add(String phone, String model) {
        SQLiteDatabase writableDatabase = db.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put("phonenumber", phone);
        Log.d("測試", "Add: "+phone);
        contentValues.put("model", model);
        //如果insert的值位-1   則說明插入失敗
        long insert = writableDatabase.insert(tablename, null, contentValues);
        writableDatabase.close();
        //如果插入進數據庫 則返回true
        if (insert != -1) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 刪除數據庫中的數據
     *
     * @param phone
     * @return
     */
    public Boolean Delete(String phone) {
        SQLiteDatabase writableDatabase = db.getWritableDatabase();
        //返回值爲0 說明沒有刪除數據
        int delete = writableDatabase.delete(tablename, "phonenumber=?", new String[]{phone});
        writableDatabase.close();
        if (delete != 0) {
            return true;
        } else {
            return false;
        }

    }

    /**
     * 更改攔截模式
     *
     * @param phone
     * @param model
     * @return
     */
    public Boolean Update(String phone, String model) {
        SQLiteDatabase writableDatabase = db.getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        contentValues.put("model", model);
        int update = writableDatabase.update(tablename, contentValues, "phonenumber=?",new String[]{phone});
        writableDatabase.close();
        if (update==0){
            return false;
        }else {
            return true;
        }

    }


    /**
     * 查找數據的操作  主要是查找phone的model
     * @param phone
     * @return
     */
    public String Query(String phone){
        String model = null;
        SQLiteDatabase readableDatabase = db.getReadableDatabase();
        Cursor query = readableDatabase.query(tablename, new String[]{"model"}, "phonenumber=?", new String[]{phone}, null, null, null);
        while (query.moveToNext()){
            model = query.getString(0);
        }
       return model;
    }


}

這個類中有個DBHelper的實例變量,恰好在構造方法中有初始化了這個實例變量,這個就能使用這個數據庫了,記住這個上下文參數也要傳進入,這樣就可以利用這些db進行增刪改查了。具體的使用方法基本就是上面這幾種了。更新,刪除,插入如果失敗返回的是-1,因此只要判斷返回的是不是-1即可。查詢函數是比較難寫的一個方法,因爲他的參數特別多,需要加以記憶!還有就是這個SQL語句很簡單,並沒有涉及到很難得查詢,因此那更難得查詢應該怎樣寫,這還是一個自己沒有嘗試得地方。

第三步:在Activity中掉用這個DBdao即可使用:

BlackNumberDao blackNumberDao = new BlackNumberDao(getApplicationContext());
Boolean add = blackNumberDao.Add(phone, model);

這樣就完成了數據庫的使用,現在回想起來,使用這個數據庫也挺簡單的,每次看一遍代碼,自己都會有新的體會!

第七個知識點:Fragment的使用

這個知識點的內容也是非常中要的,具體的重要原理咱不講,咱只說如何使用。

用一個小小的Demo來說明如何使用Fragment:像微信的主頁面那樣,按下面的一張圖片就跳轉到一個界面,可以來回的跳轉。

在做這個Demo的時候,我認爲Fragment還不容易嗎!!不就是利用replace和add等方法加上去不就行了,結果是,我居然搞了2個多小時,把我的激情都給搞沒有了,再一次被編程打擊了!!但是最終的結果還好,自己完成了這個小小的需求,自己遇到了三個錯誤,搞了半天。

錯誤一:自己把自己的Activity頁面搞混了

這是一個小錯誤,我覺得是因爲自己好多天沒有學習Android所導致的,最近在寫JavaWeb的東西,這個問題不大,自己看界面的錯誤就解決了

錯誤二:對於import android.app.Fragment和android.support.v4.app.Fragment的問題

我在Fragment中使用android.support.v4.app.Fragment,結果在Activity中使用import android.app.Fragment,結果是一致報錯,我心想,我自己不會這麼白癡吧,這點知識還能打錯了,自己找了半天,才解決了這個問題,具體他們兩個的區別點擊這篇博客看看吧,一定要保持一致的包,這樣纔不會出錯。

錯誤三:java.lang.IllegalStateException: commit already called報這個錯誤

到了最後了,我心想該沒有錯了吧,結果又給我提個錯,結果百度一搜,答案就出來了,原因如下:

是因爲你的ft事務是全局的變量,只能commit一次。所以用兩個局部ft事務去做commit即可。

所以說,一個ft只能執行一次commit操作,而且,一定要保證ft爲局部變量,否則可能會拋出這個錯誤,

還有一個最最最最最重要的錯誤,如下:下面兩段代碼中,這三句的

 FragmentManager fm = getFragmentManager();
 FragmentTransaction ft = fm.beginTransaction();
 Fragment fragment = null;

的作用範圍是一樣的嗎????

    private void initEvent() {
        View.OnClickListener pagechange = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentManager fm = getFragmentManager();
                FragmentTransaction ft = fm.beginTransaction();
                Fragment fragment = null;
                switch (v.getId()) {
                    case R.id.ib_home_home:
                        fragment = new HomeFragment();
                        break;
                    case R.id.ib_home_check:
                        fragment = new CheckFragment();
                        break;
                    case R.id.ib_home_myinfo:
                        fragment = new MyinfoFragment();
                        break;
                    default:
                        break;
                }
                ft.replace(R.id.home_content_fragment, fragment);
                ft.commit();
            }
        };
 private void initEvent() {
        View.OnClickListener pagechange = new View.OnClickListener() {
                 FragmentManager fm = getFragmentManager();
                FragmentTransaction ft = fm.beginTransaction();
                Fragment fragment = null;
            @Override
            public void onClick(View v) {
               
                switch (v.getId()) {
                    case R.id.ib_home_home:
                        fragment = new HomeFragment();
                        break;
                    case R.id.ib_home_check:
                        fragment = new CheckFragment();
                        break;
                    case R.id.ib_home_myinfo:
                        fragment = new MyinfoFragment();
                        break;
                    default:
                        break;
                }
                ft.replace(R.id.home_content_fragment, fragment);
                ft.commit();
            }
        };

答案是不一樣的,第二種代碼就會報上面那種錯。(我認爲第二種方式ft已經是局部變量了,但是他不是,必須是onClick種的變量纔是局部變量)具體的代碼我就不展示了,畢竟是一個小小的Demo,不難,但是易錯點多,我輩尚需努力啊!

第八個知識點,也是我認爲最難理解的知識點:ListView的使用

ListView用到是會用,但是對於一些具體的細節問題,需要進步的去理解,去慢慢的琢磨

下面就先利用簡單的list做個簡單的demo,再利用很多的數據做一個進階版的Demo,就是一個用系統的,一個用自定義的item

剛寫好代碼就遇到一個錯誤,這個錯誤是這樣的Error running HomeActivity: The activity must be exported or contain an intent-filte

怎麼都運行不了了,然後到網上一搜,發現我在運行一個activity界面,並不是一個app程序:如下所示:

listview的使用也分三個步驟:

第一:首先在佈局裏聲明ListView組件:


    <ListView
        android:id="@+id/lv_listview_demo1"
        android:divider="#000"
        android:dividerHeight="5dp"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </ListView>

divider屬性是指兩個item之間的邊框線的顏色 ,dividerHeight是指邊框線的高度

第二步:初始化對象

這一步很簡單,就是find viewbyid之類的步驟

第三步:直接利用SetAdapter就行了:

 private String [] data = new String[]{"aaa","aaa","aaa","aaa","aaa","aaa","aaa","aaa",

            "aaa","aaa","aaa","aaa","aaa","aaa","aaa","aaa","aaa"
    };
    private ListView lv_listview_demo1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initView();
        initData();
        initAnimation();
        initEvent();
    }

    private void initView() {
        setContentView(R.layout.activity_listview1);
        lv_listview_demo1  = findViewById(R.id.lv_listview_demo1);
    }

    private void initData() {
        lv_listview_demo1.setAdapter(new ArrayAdapter<String>( Listview1Activity.this,android.R.layout.simple_list_item_1,data) );

    }

    private void initAnimation() {


    }

    private void initEvent() {
        lv_listview_demo1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String res = parent.getItemAtPosition(position).toString();
                Toast.makeText(Listview1Activity.this,res,Toast.LENGTH_SHORT).show();
            }
        });

    }

這種方式的ListView是最簡單的,不過也是沒有進行優化的。具體的優化方式就是我不太理解的地方(開發者爲什麼都知道這個bug了,爲什麼還是不在最基本的源碼部分修改這個bug呢?)

接下來就是自定義一個listview了,開始自己寫吧!

在這就只給一部分代碼:

 private ListView lv_listview_demo2;
    private String [] data = new String[]{"aaa","aaa","aaa","aaa","aaa","aaa","aaa","aaa",
            "aaa","aaa","aaa","aaa","aaa","aaa","aaa","aaa","aaa"
    };



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


        initView();
        initData();
        initAnimation();
        initEvent();
    }

    private void initView() {
        setContentView(R.layout.activity_listview2);
        lv_listview_demo2 = findViewById(R.id.lv_listview_demo2);

    }

    private void initData() {
        lv_listview_demo2.setAdapter(new DemoAdapter());

    }

    private void initAnimation() {

    }

    private void initEvent() {

    }
public class DemoAdapter extends BaseAdapter{

    @Override
    public int getCount() {
        return data.length;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View inflate = View.inflate(getApplicationContext(), R.layout.listview_item, null);
        TextView title = inflate.findViewById(R.id.title);
        TextView content = inflate.findViewById(R.id.content);
        title.setText(data[position]);
        content.setText(data[position]);
        return inflate;
    }
}

 

像這種級別的代碼,一看就會,不過對於listview,這些都不行,還得學會他的優化方式,但是這篇博客,不說關於優化的方式,因爲自己還沒有學的很透徹,等我理解了具體的操作方式,我準備專門寫一篇博客講述爲什麼要優化listview。

這篇博客就到這吧,寫了一下午的博客和代碼,有點累了,不過很充實,我喜歡這種感覺!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章