private Handler mHandler = new Handler() {
@OverridepublicvoidhandleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case UPDATE_MESSAGE:
int insertCount = 0;
MusicInfo tempMusic = (MusicInfo) msg.obj;
if (SongScanActivity.this != null) {
songCount++;
scancount_tv.setText(String.valueOf(songCount));
scannow_tv.setText(tempMusic.getTitle() + "--" + tempMusic.getPath());
//insert the music that not into database into databaseif (mifDao.load(tempMusic.getSongId()) == null) {
daoSession.insert(tempMusic);
insertCount++;
}
if (SweetApplication.DEBUG) {
Log.i("com.cvil.debug", String.valueOf(insertCount));
}
}
break;
}
}
};
还有一种比较危险的情况就是在你退出当前界面之后,这个线程并不会停止它的工作,它将继续扫描你手机里面的音乐,而如果这时候你退出了这个界面,它继续发送消息给handler,handler在进行UI的改变的时候无法找到控件导致控指针异常,这时候又涉及到了线程的控制,我们在扫描的时候, while (cursor.moveToNext() && IS_CONTINUE_SCAN)可以看到在循环的时候有这个全局变量IS_CONTINUE_SCAN的控制,只有在true的时候才继续循环,否则就退出循环,一旦推出循环,那么这个线程将结束它的工作,从而进入一种睡眠或者说杀死的状态,这时候就不会继续消息的发送以及悲剧的导致。这个变量我在onDestroy方法中进行了控制。
@OverrideprotectedvoidonDestroy() {
super.onDestroy();
IS_CONTINUE_SCAN = false;
try {
Thread.sleep(UPDATE_MUSIC_INFO_DURATION);//wait for the thread stop
} catch (InterruptedException e) {
e.printStackTrace();
}
scanMusicThread.interrupt(); //interrupt the thread to stop the work of the thread
}
当界面被销毁的时候,这个成员变量将会被复制false,停止子线程中的循环。从而保证界面的安全刷新。
以下附上完整代码:
package com.huwei.sweetmusicplayer;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore.Audio.Media;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.huwei.sweetmusicplayer.dao.DaoSession;
import com.huwei.sweetmusicplayer.dao.MusicInfoDao;
import com.huwei.sweetmusicplayer.models.MusicInfo;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.ViewById;
import java.util.ArrayList;
import java.util.List;
@EActivity(R.layout.activity_songscan)
publicclassSongScanActivityextendsBaseActivity {privatestaticfinalboolean IS_FAVORITE = false;
private List<MusicInfo> musicList = new ArrayList<>();
private Uri contentUri = Media.EXTERNAL_CONTENT_URI;
private ContentResolver resolver;
private ScanMusicThread scanMusicThread;
privateint songCount = 0;
/**
* The columns choose to get from your phone
*/private String[] projection = {Media._ID, Media.DISPLAY_NAME, Media.DATA, Media.ALBUM, Media.ARTIST, Media.DURATION, Media.SIZE, Media.ALBUM_ID};
/**
* filter condition
*/
String where = "mime_type in ('audio/mpeg','audio/x-ms-wma') and is_music > 0";
/**
* sort order
*/private String sortOrder = Media.DATA;
private DaoSession daoSession;
private MusicInfoDao mifDao;
privatestaticfinalint UPDATE_MESSAGE = 0;
privatestaticfinalint UPDATE_MUSIC_INFO_DURATION = 200;
privateboolean IS_CONTINUE_SCAN = true;
@ViewById
TextView scannow_tv;
@ViewById
TextView scancount_tv;
@ViewById
Button scanfinish_btn;
private Handler mHandler = new Handler() {
@OverridepublicvoidhandleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case UPDATE_MESSAGE:
int insertCount = 0;
MusicInfo tempMusic = (MusicInfo) msg.obj;
if (SongScanActivity.this != null) {
songCount++;
scancount_tv.setText(String.valueOf(songCount));
scannow_tv.setText(tempMusic.getTitle() + "--" + tempMusic.getPath());
//insert the music that not into database into databaseif (mifDao.load(tempMusic.getSongId()) == null) {
daoSession.insert(tempMusic);
insertCount++;
}
if (SweetApplication.DEBUG) {
Log.i("com.cvil.debug", String.valueOf(insertCount));
}
}
break;
}
}
};
@ViewById
Toolbar toolbar;
@AfterViewsvoid init() {
toolbar.setVisibility(View.VISIBLE);
toolbar.setTitle("歌曲扫描");
toolbar.setNavigationIcon(R.drawable.mc_back);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@OverridepublicvoidonClick(View v) {
onBackPressed();
}
});
}
@OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
resolver = getContentResolver();
daoSession = SweetApplication.getDaoSession();
mifDao = daoSession.getMusicInfoDao();
scanMusicThread = new ScanMusicThread();
scanMusicThread.start();
}
@OverrideprotectedvoidonDestroy() {
super.onDestroy();
IS_CONTINUE_SCAN = false;
try {
Thread.sleep(UPDATE_MUSIC_INFO_DURATION);//wait for the thread stop
} catch (InterruptedException e) {
e.printStackTrace();
}
scanMusicThread.interrupt(); //interrupt the thread to stop the work of the thread
}
/**
* A thread to scan the music in your phone
*/
class ScanMusicThread extends Thread {
@Overridepublicvoidrun() {
super.run();
MusicInfo musicInfo;
Cursor cursor = resolver.query(contentUri, projection, where, null, sortOrder);
if (cursor != null) {
while (cursor.moveToNext() && IS_CONTINUE_SCAN) {
String title = cursor.getString(cursor.getColumnIndex(Media.DISPLAY_NAME));
String album = cursor.getString(cursor.getColumnIndex(Media.ALBUM));
long albumID = cursor.getLong(cursor.getColumnIndex(Media.ALBUM_ID));
long id = cursor.getLong(cursor.getColumnIndex(Media._ID));
int duration = cursor.getInt(cursor.getColumnIndex(Media.DURATION));
long size = cursor.getLong(cursor.getColumnIndex(Media.SIZE));
String artist = cursor.getString(cursor.getColumnIndex(Media.ARTIST));
String path = cursor.getString(cursor.getColumnIndex(Media.DATA));
musicInfo = new MusicInfo(id, albumID, title, artist, duration, path, IS_FAVORITE);
musicList.add(musicInfo);
if (mHandler != null && SongScanActivity.this != null) {
try {
Thread.sleep(UPDATE_MUSIC_INFO_DURATION);
} catch (InterruptedException e) {
e.printStackTrace();
}
Message msg = new Message();
msg.obj = musicInfo;
msg.what = UPDATE_MESSAGE;
mHandler.sendMessage(msg);
}
}
}
}
}
}