1

我是 Android 编程新手,对它只有非常基本的了解。我正在尝试了解基本的多线程。

我按照教程创建了一个基本线程并显示了一个progressDialog,它只是在单击按钮时将500条记录添加到数据库中。

    public void btnAddClick(View v) {
    // Create progress dialog to show status
    dialog = ProgressDialog.show(MainActivity.this, "Loading", "Updating database...");

    h = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            dialog.dismiss();
        }
    };

    // Create a new thread
    new Thread() {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            super.run();
            // Time consuming task here
            try {
                Thread.sleep(1);
                UpdateDB();
                h.sendEmptyMessage(0);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    .start();
    //UpdateDB();
}

使用此代码,我在 IDE 中收到警告:此 Handler 类应该是静态的,否则可能会发生泄漏。

我还有 2 个按钮查看和清除,我为每个按钮使用相同的代码,只是 UpdateDB(); 成为 ViewDB(); 和 ClearDB();

代码编译并且 AddClick 工作完美,但如果我尝试使用 ViewClick 或 ClearClick 然后我的应用程序崩溃,在查看有时对话框显示几秒钟然后我的应用程序崩溃。

是不是资源泄露造成的?有人可以向我展示一个如何使处理程序静态的示例,以便我在使用它时避免问题。

该活动的完整源代码在这里:

    import android.app.Activity;
import android.app.ProgressDialog;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity {
    protected ProgressDialog dialog;
    protected Handler h;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    DBAdapter myDb;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        checkDataBase();    
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();  
        closeDB();
    }

    private void openDB() {
        myDb = new DBAdapter(this);
        myDb.open();
    }

    private void closeDB() {
        myDb.close();
    }

    private void displayText(String message) {
        TextView textView = (TextView) findViewById(R.id.textDisplay);
        textView.setText(message);
    }

    public void btnAddClick(View v) {
        // Create progress dialog to show status
        dialog = ProgressDialog.show(MainActivity.this, "Please Wait", "Updating database...");

        h = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                dialog.dismiss();
            }
        };

        // Create a new thread
        new Thread() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                super.run();
                // Time consuming task here
                try {
                    Thread.sleep(1);
                    UpdateDB();
                    h.sendEmptyMessage(0);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        .start();
        //UpdateDB();
    }

    public void btnClearClick(View v) {
        // Create progress dialog to show status
        dialog = ProgressDialog.show(MainActivity.this, "Please Wait", "Deleting database...");

        h = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                dialog.dismiss();
            }
        };

        // Create a new thread
        new Thread() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                super.run();
                // Time consuming task here
                try {
                    Thread.sleep(1);
                    ClearDB();
                    h.sendEmptyMessage(0);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        .start();
    }

    public void btnViewClick(View v) {
        // Create progress dialog to show status
        dialog = ProgressDialog.show(MainActivity.this, "Please Wait", "Displaying records...");

        h = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                dialog.dismiss();
            }
        };

        // Create a new thread
        new Thread() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                super.run();
                // Time consuming task here
                try {
                    Thread.sleep(1);
                    ViewDB();
                    h.sendEmptyMessage(0);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        .start();

    }

    // Display full database inside TextView
    private void displayRecordSet(Cursor cursor) {
        String message = "";
        // populate the message from the cursor

        // Reset cursor to start, checking to see if there's data:
        if (cursor.moveToFirst()) {
            do {
                // Process the data:
                int id = cursor.getInt(DBAdapter.COL_ROWID);
                String make = cursor.getString(DBAdapter.COL_MAKE);
                String model = cursor.getString(DBAdapter.COL_MODEL);
                String year = cursor.getString(DBAdapter.COL_YEAR);
                String tyreSize = cursor.getString(DBAdapter.COL_TYRESIZE);
                String front = cursor.getString(DBAdapter.COL_FRONT);
                String rear = cursor.getString(DBAdapter.COL_REAR);

                // Append data to the message:
                message += "id=" + id
                           +", make=" + make
                           +", model=" + model
                           +", year=" + year
                           +", tyreSize=" + tyreSize
                           +", front=" + front
                           +", rear=" + rear
                           +"\n";
            } while(cursor.moveToNext());
        }

        // Close the cursor to avoid a resource leak.
        cursor.close();

        displayText(message);
    }

    // Checks database file exists during OnCreate();
    private boolean checkDataBase() {
        SQLiteDatabase checkDB = null;
        try {
            String DB_FULL_PATH = "/data/data/com.digitak.mytyrepressure/databases/myDb";
            checkDB = SQLiteDatabase.openDatabase(DB_FULL_PATH , null,
                    SQLiteDatabase.OPEN_READONLY);
            checkDB.close();
        } catch (SQLiteException e) {
            // database doesn't exist yet.
            System.out.println("Database Doesnt Exist...Creating");
            openDB();
        }
        return checkDB != null ? true : false;
    }

    // Adds 500 Records to the database for testing purposes
    public void UpdateDB() {
        int x = 0;
        while (x < 500) {
            myDb.insertRow("Ford", "KA", "1996-2003", "155/70R13", "31", "26");
            x++;
        }
    }

    public void ViewDB() {
        Cursor cursor = myDb.getAllRows();
        displayRecordSet(cursor);
    }

    public void ClearDB() {
        myDb.deleteAll();
    }

}

感谢您的时间。

4

2 回答 2

0

可能它没有因为泄漏而发生,但它为什么会发生,如果我们看到 catlog 会更容易说..

旁注.. WTH 是 Thread.sleep(1) 用于???

旁注2:你根本不应该在这里使用线程。如果你需要在后台执行任务,一般来说有 AsyncTask 类。专门针对 DB 事务,还有更好的内容提供者和加载器概念。

希望我能有所帮助,以便您可以朝着正确的方向前进。

于 2013-10-17T07:34:19.520 回答
0

创建Handler时添加此参数:Looper.getMainLooper()

Handler handler = new Handler(Looper.getMainLooper()){...
}

这应该删除警告

于 2017-02-11T11:42:08.433 回答