2017-11-04 167 views
0

我正在嘗試構建小型音板。我收到內存泄漏錯誤,應用程序崩潰。任何人都可以告訴我,如果我的代碼有一些問題或效率低下。我有10個類似Activity1的活動。有什麼辦法可以使代碼更高效和快速。我不知道這部分代碼是造成內存泄漏錯誤在仿真器中運行時發生內存泄漏錯誤

Sound.java

public class Sound 
     implements OnClickListener,OnCreateContextMenuListener, OnMenuItemClickListener{ 

    static final private int MENU_RINGTONE = Menu.FIRST; 
    static final private int MENU_NOTIFICATION = MENU_RINGTONE + 1; 
    static final private int MENU_MUSIC = MENU_NOTIFICATION + 1; 
    static final private int MENU_SET = MENU_MUSIC + 1; 

    private Activity mParent; 
    private int mResourceId; 
    private String mName; 
    private int mButtonID; 

    private static Player mPlayer; 
    public static Player getPlayer() { return mPlayer; } 
    public static void setPlayer(Player value) { 
     mPlayer = value; 
    } 


    private static boolean mDoSet; 
    public static boolean getmDoSet() { return mDoSet; } 
    public static void setmDoSet(boolean value) { mDoSet = value; } 

    enum Action {Ringtone, Notification, Music}; 
    private boolean doSet; 
    private Action mAction; 

    Sound(Activity Parent, int RawResId, int ButtonID, String Name){ 
     mParent = Parent; 
     mResourceId = RawResId; 
     mName = Name; 
     mButtonID = ButtonID; 
    } 
    public void Initialize() { 
     mParent.findViewById(mButtonID).setOnClickListener(this); 
     mParent.findViewById(mButtonID).setOnCreateContextMenuListener(this); 
    } 

    @Override 
    public void onClick(View v) { 
     if (mPlayer != null){ 
      mPlayer.play(mParent.getBaseContext(), mResourceId); 
     } 
    } 


    @Override 
    public void onCreateContextMenu(ContextMenu menu, View v, 
            ContextMenuInfo menuInfo) { 

     mParent.onCreateContextMenu(menu, v, menuInfo); 
     menu.setHeaderTitle("Context Menu"); 
     menu.add(0, MENU_RINGTONE, 0, R.string.SaveRingtone).setOnMenuItemClickListener(this); 
     menu.add(0, MENU_NOTIFICATION, 0, R.string.SaveNotification).setOnMenuItemClickListener(this); 
     menu.add(0, MENU_MUSIC, 0, R.string.SaveMusic).setOnMenuItemClickListener(this); 

    } 

    @Override 
    public boolean onMenuItemClick(MenuItem item) { 

     switch (item.getItemId()) 
     { 
      case MENU_RINGTONE: 
       mAction = Action.Ringtone; 
       break; 
      case MENU_NOTIFICATION: 
       mAction = Action.Notification; 
       break; 
      case MENU_MUSIC: 
       mAction = Action.Music; 
       break; 
     } 


     String name = mName.toLowerCase().replace(' ', '_'); 
     return SaveSound(mParent,name, mName, mResourceId); 

    } 
    public boolean SaveSound(Activity Parent, String filename, String Title, int ressound) { 
     byte[] buffer = null; 
     InputStream fIn = Parent.getBaseContext().getResources().openRawResource(ressound); 
     int size = 0; 

     try { 
      size = fIn.available(); 
      buffer = new byte[size]; 
      fIn.read(buffer); 
      fIn.close(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      return false; 
     } 
     String path1 = android.os.Environment.getExternalStorageDirectory().getPath() + "/media/audio/ringtones/"; 
     String path2 = android.os.Environment.getExternalStorageDirectory().getPath() + "/media/audio/notifications/"; 
     boolean saved = false; 

     switch (mAction){ 
      case Ringtone: 
       saved = save(Parent, filename, Title, buffer,path1); 
      case Notification: 
       saved = save(Parent, filename, Title, buffer, path2); 
      case Music: 
     }; 

     if (saved) { 
      return true; 
     } else { 
      return false; 
     } 

    } 
    public boolean save(Activity Parent, String filename, String Title, 
         byte[] buffer, String path) { 


     boolean exists = (new File(path)).exists(); 
     if (!exists){new File(path).mkdirs();} 

     FileOutputStream save; 
     try { 
      save = new FileOutputStream(path+filename); 
      save.write(buffer); 
      save.flush(); 
      save.close(); 
     } catch (FileNotFoundException e) { 
      // TODO Auto-generated catch block 
      return false; 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      return false; 
     } 

     Parent.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://"+path+filename))); 

     File k = new File(path, filename); 

     ContentValues values = new ContentValues(); 
     values.put(MediaStore.MediaColumns.DATA, k.getAbsolutePath()); 
     values.put(MediaStore.MediaColumns.TITLE, Title); 
     values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/ogg"); 
     values.put(MediaStore.Audio.Media.ARTIST, " "); 
     values.put(MediaStore.Audio.Media.IS_RINGTONE, true); 
     values.put(MediaStore.Audio.Media.IS_NOTIFICATION, true); 
     values.put(MediaStore.Audio.Media.IS_ALARM, true); 
     values.put(MediaStore.Audio.Media.IS_MUSIC, true); 

     //Insert it into the database 
     Uri uri = MediaStore.Audio.Media.getContentUriForPath(k.getAbsolutePath()); 
     Uri newUri = Parent.getContentResolver().insert(uri, values); 

     // set the ringtone 

     if (doSet == true && mAction == Action.Ringtone 
       || mAction == Action.Notification) { 

      int type = RingtoneManager.TYPE_RINGTONE; 
      switch (mAction) { 
       case Ringtone: 
        type = RingtoneManager.TYPE_RINGTONE; 
        break; 
       case Notification: 
        type = RingtoneManager.TYPE_NOTIFICATION; 
      } 

      RingtoneManager.setActualDefaultRingtoneUri(mParent, type, newUri); 
     } 

     return true; 
    } 

} 

Player.java

public class Player { 
    private MediaPlayer mp; 
    public Player(){ 
     mp = new MediaPlayer(); 
    } 
    public void play(Context c, int r) { 
     if (mp==null) 
      return; 
     if (mp.isPlaying()){ 
      mp.stop(); 
      mp.release(); 
     }else{ 
      mp = MediaPlayer.create(c, r); 
      mp.start(); 
     } 
    } 


    public void stop() { 
     if (mp==null) 
      return; 
     if (mp.isPlaying()){ 
      mp.stop(); 
      mp.release(); 
     } 
    } 


} 

Activity1.java

public class Activity1 
     extends Activity { 


    private Player p; 

    Sound Sounds[] = { 
      new Sound(this, R.raw.baboon, R.id.Animal1, "") 
      , new Sound(this, R.raw.baligator, R.id.Animal2, "") 
      , new Sound(this, R.raw.bat, R.id.Animal3, "") 

    }; 



    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.animals); 


     p = new Player(); 
     Sound.setPlayer(p); 

     for (int i = 0; i < Sounds.length; i++) { 
      Sounds[i].Initialize(); 
     } 


    } 


    public boolean onCreateOptionsMenu(Menu menu) { 
     MenuInflater inflater = getMenuInflater(); 
     inflater.inflate(R.menu.menu, menu); 
     return true; 
    } 


    @Override 
    public void onBackPressed() { 
     super.onBackPressed(); 
     p.stop(); 
    } 

    @Override 
    protected void onPause() 
    { 
    super.onPause(); 
    p.stop(); 
    } 

} 

回答

0

在你Sound您正在持有對mParent活動的參考,並且您從未讓t他將活動設置爲null,因此活動永遠不會被垃圾收集。

老實說,它看起來像你試圖將所有的活動代碼提取到不同的類來創建一個'模板'類型,但沒有得到Android生命週期的影響。

+0

我該如何解決它,請你解釋一下 – user7511549

相關問題