day4.22总结_CursorLoader和service的启动模式

一、CursorLoader对象

1此对象内置一个异步任务对象,可以通过此对象在工作线程访问一个ContentProvider对象,然后获得我们需要的数据。

2CursorLoader对象的启动:

借助ActivityLoaderManager对象的initLoader(int id,Bundle args,LoaderCallBacks call)方法启动

3CursorLoader初始化时会执行LoaderCallBacksonCreateLoader方法,一般此方法中创建一个CursorLoader对象。

4CursorLoader数据加载完成以后会回调onLoadFinished方法,可以在方法中更新UI.

 

顺序:LoaderManager.initLoader》》LoaderCallBacks.nCreateLoader》》onLoadFinished(更新UI

例子1:自定义Adapter加载音乐

public class MainActivity extends ListActivity implements MusicRetrieverListener,OnPreparedListener,OnCompletionListener{

 

private List<Music> musics=new ArrayList<Music>();

private MusicAdapter adapter;

MusicRetriever retriever;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//setContentView(R.layout.activity_main);

 

retriever=new MusicRetriever(this);

retriever.prepare(getLoaderManager())开始加载音乐

adapter=new MusicAdapter(this,android.R.layout.simple_list_item_2,musics);

setListAdapter(adapter);

}

private MediaPlayer mPlayer;

@Override

protected void onListItemClick(ListView l, View v, int position, long id) {

Music m=(Music) l.getItemAtPosition(position);

String path=m.getData();

if(mPlayer==null){

mPlayer=new MediaPlayer();

mPlayer.setOnPreparedListener(this);

mPlayer.setOnCompletionListener(this);

}

mPlayer.reset();//重置(可以再次点击时播放其它音乐)

try{

//设置音乐路径

mPlayer.setDataSource(path);

//加载音乐

//mPlayer.prepare();

mPlayer.prepareAsync();//异步加载

//播放音乐

//mPlayer.start();

}catch(Exception e){e.printStackTrace();};

}

/**数据加载完成执行此方法,可在此方法中更新UI*/

@Override

public void onRetriverFinished(List<Music> data) {

musics.clear();

musics.addAll(data);

adapter.notifyDataSetChanged();

}

 

@Override

public boolean onOptionsItemSelected(MenuItem item) {

if(item.getItemId()==R.id.refreshId){

retriever.restartPrepare(getLoaderManager());

}

return super.onOptionsItemSelected(item);

}

 

@Override

protected void onDestroy() {

super.onDestroy();

if(mPlayer!=null){

mPlayer.release();//释放资源

mPlayer=null;

}

}

@Override

public void onPrepared(MediaPlayer mp) {

mPlayer.start();

}

@Override

public void onCompletion(MediaPlayer mp) {

mPlayer.start();

}

}

public class MusicRetriever implements LoaderCallbacks<Cursor>{

private Context context;

public MusicRetriever(Context context){

this.context=context;

}

/**通过此方法加载音乐信息*/

public void prepare(LoaderManager loaderManager){

//初始化CursorLoader对象

//此时会执行onCreateLoader方法

loaderManager.initLoader(0,null,this);

}

public void restartPrepare(LoaderManager loaderManager){

loaderManager.restartLoader(0, null, this);

}

@Override

public Loader<Cursor> onCreateLoader(int id, Bundle args) {

Log.i("TAG", "onCreateLoader");

return new CursorLoader(

context,// Context    查询音乐

Media.EXTERNAL_CONTENT_URI,// Provider's content URI

null, // Columns to return

null,// Return all rows

null,                           // No search arguments

null);  

// Default search order

}

/**此方法运行在主线程*/

@Override

public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {

Log.i("TAG", "onLoadFinished");

processMusicData(cursor);

}

private void processMusicData(Cursor cursor) {

if(cursor==null){

Log.i("TAG", "query error!");

return;

}

if(!cursor.moveToNext()){

Log.i("TAG", "no data");

return;

}

List<Music> list=new ArrayList<Music>();

do{//循环依次取一行,一行对应一个music对象   加载音乐

Music m=new Music();

m.setId(cursor.getInt(cursor.getColumnIndex(Media._ID)));

m.setName(cursor.getString(cursor.getColumnIndex(Media.DISPLAY_NAME)));

m.setData(cursor.getString(cursor.getColumnIndex(Media.DATA)));

m.setArtist(cursor.getString(cursor.getColumnIndex(Media.ARTIST)));

list.add(m);

}while(cursor.moveToNext());

cursor.close();

//加载完成通知更新(接口回调)

((MusicRetrieverListener)context).onRetriverFinished(list);

 

}

@Override

public void onLoaderReset(Loader<Cursor> loader) {

Log.i("TAG", "onLoaderReset");

}

}

public class MusicAdapter extends BaseAdapter{

 

private Context context;

private int resource;

private List<Music> musics;

public MusicAdapter(Context context,int resource,List<Music> musics){

this.context=context;

this.resource=resource;

this.musics=musics;

}

@Override

public int getCount() {

return musics.size();

}

@Override

public Object getItem(int position) {

return musics.get(position);

}

 

@Override

public long getItemId(int position) {

return musics.get(position).getId();

}

 

@Override

public View getView(int position, View convertView, ViewGroup parent) {

//1.item view

View view;

ViewHolder vholder;

if(convertView==null){

view=View.inflate(context,resource,null);

vholder=new ViewHolder();

vholder.nameTv=(TextView) view.findViewById(android.R.id.text1);

vholder.artistTv=(TextView) view.findViewById(android.R.id.text2);

view.setTag(vholder);

}else{

view=convertView;

vholder=(ViewHolder) convertView.getTag();

}

//2.item data

    Music m=musics.get(position);

//3.set item data to item view

vholder.nameTv.setText(m.getName());

vholder.artistTv.setText(m.getArtist());

return view;

}

class ViewHolder{

TextView nameTv;

TextView artistTv;

}

}

public interface MusicRetrieverListener {  接口

void onRetriverFinished(List<Music> data);

}

 

例子2:使用SimpleCursorAdapter加载音乐

public class MainActivity extends ListActivity implements LoaderCallbacks<Cursor> {

 

private SimpleCursorAdapter adapter;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

 

//setContentView(R.layout.activity_main);

adapter=new SimpleCursorAdapter(this,android.R.layout.simple_list_item_2,

null ,            可以先为空

new String[]{Media.TITLE,Media.ARTIST},    字段名

new int[]{android.R.id.text1,android.R.id.text2},    textviewID

CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);

setListAdapter(adapter);

//启动CursorLoader

getLoaderManager().initLoader(0, null, this);

}

@Override    加载音乐

public Loader<Cursor> onCreateLoader(int id, Bundle args) {

return new CursorLoader(this,Media.EXTERNAL_CONTENT_URI, null, Media.IS_MUSIC+"=1",null, null);

}

@Override   加载完执行

public void onLoadFinished(Loader<Cursor> loader, Cursor data) {

adapter.changeCursor(data);

}

@Override   重置

public void onLoaderReset(Loader<Cursor> loader) {

adapter.changeCursor(null);

}

private MediaPlayer mPlayer;

@Override

protected void onListItemClick(

ListView l, View v,int position, long id) {

Cursor c=(Cursor)l.getItemAtPosition(position);

playMusic(c.getString(c.getColumnIndex(Media.DATA)));

//c.moveToPosition(position)

}

private void playMusic(String path){

if(mPlayer==null){

mPlayer=new MediaPlayer();    播放音乐

}

mPlayer.reset();

try {

mPlayer.setDataSource(path);

mPlayer.prepare();

mPlayer.start();

} catch (Exception e) {

e.printStackTrace();

}

}

@Override

protected void onDestroy() {

// TODO Auto-generated method stub

super.onDestroy();

if(mPlayer!=null){

mPlayer.release();

mPlayer=null;

}

}

}

 

 

二、Service 组件

(1)Service 是什么(What)

1)Android 中的一个应用组件(生命周期方法)

对于长时间的耗时操作是直接起工作线程,还是启service?  建议:在Service中启工作线程。

2)Android 中的一个后台服务(可以长时间运行于后台)

 

3)为什么不在activity启工作线程执行耗时操作呢?

 

因为当activity工作于后台处于停止状态时,它所在进程的生命力就会比较薄弱,在内存不足时可能会被杀死。

 

4Android 中的进程可以分为如下几种类型

 

a.前台进程(可见,可以与用户交互)

b.可见进程(可见,但不能与用户交互)

c.服务进程(后台有service在运行)

d后台进程(没有service组件,所有的activity都处于停止状态)

e空进程(没有任何组件在运行的进程)

 

以上进程的生命力,从高到低。

(2)Android 中的Service 的应用场合(when,why)

执行长时间耗时操作时时,可以考虑在service组件中执行,例如音乐的播放,股票信息的时加载等。

 

记住:并不是耗时都要写到service,短时间的耗时完全可以在activity中启工作线程执行。

 

(3)Android Service 的类型

 

1)启动模式的Service

2)绑定模式的Service

3)混合模式的Service

 

我们在理解这些模式的service时,需要重点掌握这些模式service对象的生命期,以及其生命周期方法,我们可以在对应的生命周期方法中执行业

务。

 

(4)Android 中启动模式的Service

 

启动模式service的启动和关闭

 

1)通过startService方法启动

2)通过stopService停止,在内部可以通过stopSelf(startId)去停止

 

启动模式Service对象的生命周期方法:

1)onCreate (service创建时执行)

2)onStartCommand(每次启动都会执行)

3)onDestory(service销毁时会执行)

例子3Service启动模式

public class MainActivity extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

}

/**启动service*/

public void onClick01(View v){

Intent intent=new Intent(this,MyService01.class);

intent.putExtra("action", "play");

startService(intent);

}

/**停止service*/

public void onClick02(View v){

Intent intent=new Intent(this,MyService01.class);

stopService(intent);

}

}

public class MyService01 extends Service {

public MyService01() {

}

/**在启动模式无用*/

@Override

public IBinder onBind(Intent intent) {

// TODO: Return the communication channel to the service.

throw new UnsupportedOperationException("Not yet implemented");

}

/**此方法在service创建时执行*/

@Override

public void onCreate() {

Log.i("TAG", "onCreate()");

}

/**每次启动service都会执行*/

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

Log.i("TAG", "onStartCommand()");

Log.i("TAG", "startId="+startId);

Log.i("TAG", "flags="+flags);

String action=intent.getStringExtra("action");  接受intent

if("play".equals(action)){        判断做什么

Log.i("TAG", "playMusic");

//playMusic();

}else if("pause".equals(action)){

//pauseMusic();

}

//return START_STICKY_COMPATIBILITY//service被非正常kill以后,不保证service一定能够启动

//return START_STICKY;//service被非正常kill,它还会自动启动,但是不会重新传递intent

//return START_NOT_STICKY;//service被非正常kill,它不会自动启动

    return START_REDELIVER_INTENT;//被非正常kill以后,还会自启,同时会重新传递intent

}

/**service销毁时执行*/

@Override

public void onDestroy() {

Log.i("TAG", "onDestroy()");

}

}

 

Serivce 的子类IntentService的应用?

 

IntentService会默认启动一个工作线程,我们可以将耗时操作放在onHandleIntent中,此方

法执行结束,service会自动关闭。

 

1)启动模式Service 的粘性?(参考onStartCommand方法的返回值)

2)启动模式Service 如何通过隐式Intent启动

a)隐式意图需要在清单配置文件配置intent-filter

 

切记:service不用了,要记得停止。

例子4IntentService的应用

public class MainActivity extends Activity {

 

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

}

public void onClick(View v){

Intent intent=new Intent(this,MyService01.class);

startService(intent);

}

}

//IntentService

//1)创建时会创建一个工作线程,并构建一个handler关联工作线程的looper

//2)onStartCommand方法执行时会通过handler发送一个消息,然后回调onHandleIntent

public class MyService01 extends

IntentService{

public MyService01() {

    super("MyService01");    service名称

}

/**此方法运行在工作线程*/

@Override

protected void onHandleIntent(Intent intent) {

Log.i("TAG", "onHandleIntent-->"+Thread.currentThread().getName());

 

你可能感兴趣的:(day4.22总结_CursorLoader和service的启动模式)