(1)此对象内置一个异步任务对象,可以通过此对象在工作线程访问一个ContentProvider对象,然后获得我们需要的数据。
(2)CursorLoader对象的启动:
借助Activity的LoaderManager对象的initLoader(int id,Bundle args,LoaderCallBacks call)方法启动
(3)在CursorLoader初始化时会执行LoaderCallBacks的onCreateLoader方法,一般此方法中创建一个CursorLoader对象。
(4)在CursorLoader数据加载完成以后会回调onLoadFinished方法,可以在方法中更新UI.
顺序:LoaderManager.initLoader》》LoaderCallBacks.nCreateLoader》》onLoadFinished(更新UI)
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); } |
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; } } } |
1)Android 中的一个应用组件(生命周期方法)
对于长时间的耗时操作是直接起工作线程,还是启service? 建议:在Service中启工作线程。
2)Android 中的一个后台服务(可以长时间运行于后台)
3)为什么不在activity启工作线程执行耗时操作呢?
因为当activity工作于后台处于停止状态时,它所在进程的生命力就会比较薄弱,在内存不足时可能会被杀死。
4)在Android 中的进程可以分为如下几种类型
a.前台进程(可见,可以与用户交互)
b.可见进程(可见,但不能与用户交互)
c.服务进程(后台有service在运行)
d后台进程(没有service组件,所有的activity都处于停止状态)
e空进程(没有任何组件在运行的进程)
以上进程的生命力,从高到低。
执行长时间耗时操作时时,可以考虑在service组件中执行,例如音乐的播放,股票信息的时加载等。
记住:并不是耗时都要写到service,短时间的耗时完全可以在activity中启工作线程执行。
1)启动模式的Service
2)绑定模式的Service
3)混合模式的Service
我们在理解这些模式的service时,需要重点掌握这些模式service对象的生命期,以及其生命周期方法,我们可以在对应的生命周期方法中执行业
务。
启动模式service的启动和关闭
1)通过startService方法启动
2)通过stopService停止,在内部可以通过stopSelf(startId)去停止
启动模式Service对象的生命周期方法:
1)onCreate (service创建时执行)
2)onStartCommand(每次启动都会执行)
3)onDestory(service销毁时会执行)
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不用了,要记得停止。
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()); |