1、适配器
1.1、ArrayAdapte:现在知道ArrayAdapter通常适用TextView控件,例如Android系统中的setting(设置菜单)。
上面这个是ArrayAdapter的ListView,看上去是一片空白的。
上面这个是ArrayAdapter的Item,可以看到中间只有一个TextView。
1.2、SimpleAdapter适配器:
上面这个是SimpleAdapter的ListView。
上面这个是SimpleAdapter的Item。
2、关于ListView的优化
在使用ListView展示数据时需创建对用的Item条目展示每条数据。如果展示的数据有成千上万条,那么就需要创建成千上万个Item,这样会大大增加内存的损耗,甚至会由于内存溢出导致程序崩溃。
2.1、复用convertView:简单的说,就是底部新的数据使用顶部滑出Item的convertView。
2.2、使用ViewHolder类:意思就是,在加载Item布局时,会使用findViewById()方法找到Item布局中的各个控件,为了减少不断查找的耗时操作,可以将要加载的子View放在ViewHolder类中,当第一次创建convertView时将这些控件找出,在第二次重用convertView时可直接通过 getTag() 方法获得这些控件。
需要注意的是,LayoutInflater.from()方法需要传入一个Context对象作为参数,在Adapter中获取Context对象需要使用getApplicationContext()方法。
3、Service
两种启动Service的方式。通过startService() 方法启动服务时,执行的生命周期方法为onStartCommand() 方法,然后服务处于运行状态,直到自身调用stopSelf() 方法或其他组件调用stopService() 方法时服务停止,最终被系统销毁。使用bindService() 方法启动服务时,执行onBind() ,然后服务处于运行状态,直到调用unBindService() 方法时,服务被解绑调用onUnbind() 方法,最终被销毁。
3.1、通信方式
服务的通信方式有两种,一种是本地服务通信,一种是远程服务通信。本地服务通信是指应用程序内部的通信,远程服务通信是指两个应用程序之间的通信。使用者两种通信方式,必须保证服务是以绑定方式开启,否则无法进行通信和数据交换。
远程服务通信是通过AIDL实现的,它是一种接口定义语言。与Java中接口相似,但有些差异:AIDL定义接口的源码必须以.aidl结尾。AIDL接口中用到的数据类型,除了基本数据类型及String、List、Map、CharSequence之外,其他类型全部都需要导入包,即使它们在同一个包内。
音乐播放器实例:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical"> 6 7 <EditText 8 android:id="@+id/et_inputpath" 9 android:layout_width="match_parent" 10 android:layout_height="wrap_content" 11 android:text="Music/a.map3"/> 12 13 <LinearLayout 14 android:layout_width="match_parent" 15 android:layout_height="wrap_content" 16 android:layout_marginTop="10dp" 17 android:layout_gravity="center_horizontal" 18 android:gravity="center" 19 android:orientation="horizontal"> 20 <TextView 21 android:id="@+id/tv_play" 22 android:layout_width="0dp" 23 android:layout_height="wrap_content" 24 android:layout_weight="1" 25 android:drawablePadding="3dp" 26 27 android:gravity="center" 28 android:text="播放"/> 29 30 <TextView 31 android:id="@+id/tv_pause" 32 android:layout_width="0dp" 33 android:layout_height="wrap_content" 34 android:layout_weight="1" 35 android:drawablePadding="3dp" 36 37 android:gravity="center" 38 android:text="暂停"/> 39 </LinearLayout> 40 </LinearLayout>
1 package com.example.musicplayer; 2 3 import androidx.appcompat.app.AppCompatActivity; 4 5 import android.content.ComponentName; 6 import android.content.Intent; 7 import android.content.ServiceConnection; 8 import android.os.Bundle; 9 import android.os.Environment; 10 import android.os.IBinder; 11 import android.view.View; 12 import android.widget.EditText; 13 import android.widget.Toast; 14 15 import java.io.File; 16 17 public class MainActivity extends AppCompatActivity implements View.OnClickListener{ 18 private EditText path; 19 private Intent intent; 20 private myConn conn; 21 MusicService.MyBinder binder; 22 23 @Override 24 protected void onCreate(Bundle savedInstanceState) { 25 super.onCreate(savedInstanceState); 26 setContentView(R.layout.activity_main); 27 28 path = (EditText)findViewById(R.id.et_inputpath); 29 findViewById(R.id.tv_play).setOnClickListener(this); 30 findViewById(R.id.tv_pause).setOnClickListener(this); 31 conn = new myConn(); 32 intent = new Intent(this,MusicService.class); 33 bindService(intent,conn,BIND_AUTO_CREATE); 34 } 35 36 private class myConn implements ServiceConnection{ 37 public void onServiceConnected(ComponentName name, IBinder service){ 38 binder = (MusicService.MyBinder) service; 39 } 40 41 public void onServiceDisconnected(ComponentName name){ 42 43 } 44 } 45 46 public void onClick(View v){ 47 String pathway = path.getText().toString().trim(); 48 File SDpath = Environment.getExternalStorageDirectory(); 49 File file = new File(SDpath,pathway); 50 String path = file.getAbsolutePath(); 51 switch (v.getId()){ 52 case R.id.tv_play: 53 if(file.exists() && file.length() > 0){ 54 binder.play(path); 55 }else { 56 Toast.makeText(this,"找不到音乐文件",Toast.LENGTH_SHORT).show(); 57 } 58 break; 59 case R.id.tv_pause: 60 binder.pause(); 61 break; 62 default: 63 break; 64 } 65 } 66 67 protected void onDestroy(){ 68 unbindService(conn); 69 super.onDestroy(); 70 } 71 }
1 package com.example.musicplayer; 2 3 import android.app.Service; 4 import android.content.Intent; 5 import android.media.AudioManager; 6 import android.media.MediaPlayer; 7 import android.os.Binder; 8 import android.os.IBinder; 9 10 public class MusicService extends Service { 11 private static final String TAG = "MusicService"; 12 public MediaPlayer mediaPlayer; 13 14 class MyBinder extends Binder{ 15 //播放音乐 16 public void play(String path){ 17 try{ 18 if(mediaPlayer == null){ 19 //创建一个MediaPlayer播放器 20 mediaPlayer = new MediaPlayer(); 21 //指定参数为音频文件 22 mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); 23 //指定播放路径 24 mediaPlayer.setDataSource(path); 25 //准备播放 26 mediaPlayer.prepare(); 27 mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { 28 @Override 29 public void onPrepared(MediaPlayer mp) { 30 //开始播放 31 mediaPlayer.start(); 32 } 33 }); 34 }else{ 35 int positon = getCurrentProgress(); 36 mediaPlayer.seekTo(positon); 37 try{ 38 mediaPlayer.prepare(); 39 }catch (Exception e){ 40 e.printStackTrace(); 41 } 42 mediaPlayer.start(); 43 } 44 }catch (Exception e){ 45 e.printStackTrace(); 46 } 47 } 48 //暂停播放 49 public void pause(){ 50 if(mediaPlayer != null && mediaPlayer.isPlaying()){ 51 mediaPlayer.pause();;//暂停播放 52 }else if(mediaPlayer != null && (!mediaPlayer.isPlaying())){ 53 mediaPlayer.start(); 54 } 55 } 56 } 57 58 public void onCreate(){ 59 super.onCreate(); 60 } 61 62 //获取当前进度 63 public int getCurrentProgress(){ 64 if(mediaPlayer != null & mediaPlayer.isPlaying()){ 65 return mediaPlayer.getCurrentPosition(); 66 }else if(mediaPlayer != null &(!mediaPlayer.isPlaying())){ 67 return mediaPlayer.getCurrentPosition(); 68 } 69 return 0; 70 } 71 72 public void onDestory(){ 73 if(mediaPlayer != null){ 74 mediaPlayer.stop(); 75 mediaPlayer.release(); 76 mediaPlayer = null; 77 } 78 super.onDestroy(); 79 } 80 81 public MusicService() { 82 } 83 84 @Override 85 public IBinder onBind(Intent intent) { 86 //第一步执行onBind 方法 87 return new MyBinder(); 88 } 89 }
1 <?xml version="1.0" encoding="utf-8"?> 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 package="com.example.musicplayer"> 4 5 <application 6 android:allowBackup="true" 7 android:icon="@mipmap/ic_launcher" 8 android:label="@string/app_name" 9 android:roundIcon="@mipmap/ic_launcher_round" 10 android:supportsRtl="true" 11 android:theme="@style/AppTheme"> 12 <service 13 android:name=".MusicService" 14 android:enabled="true" 15 android:exported="true"></service> 16 17 <activity android:name=".MainActivity"> 18 <intent-filter> 19 <action android:name="android.intent.action.MAIN" /> 20 21 <category android:name="android.intent.category.LAUNCHER" /> 22 </intent-filter> 23 </activity> 24 </application> 25 26 </manifest>