본문

[2017.11.16] 73. Android 음악 플레이어 프로젝트 [최적화 3 - Thread 병렬처리]

도입

이번 포스팅에서는 Next, Prev 버튼으로 음악을 넘길 때 Viewpager가 버벅거렸던 것을 해결할 예정이다!


문제점 1

Next, Prev 음악을 선택하면 Viewpager가 조금 느려지는 현상이 발생했지만 음악이 변경되는데 이정도면 괜찮지 않나... 라는 안일한 생각을 했고 넘겼다.  그러나 다른 음악 플레이어와 비교했을 때 확실히 버벅거린다고 느껴 원인 파악을 시작했다.

 

Viewpager가 버벅거렸던 것의 원인이

1) 이미지 로딩

2) 잘못된 설계

라고 생각했다...

 

하지만 근본적인 문제는 역시 코드였다. 역시 내 잘못..

Viewpager가 버벅거리는 원인을 파악하기 위해 Viewpager가 넘어갈 때 실행되는 코드들을 이진탐색하듯 코드를 주석 처리하며 원인을 찾았다.

 

그 결과! 

1
2
3
4
5
6
7
8
9
public class PlayerController {
    // ...
    public void setMusic(final Uri musicUri) {    
        // ...        
        player = MediaPlayer.create(context, musicUri);    
        // ...
    }
    // ...
}
cs

음악이 설정될 때마다 MediaPlayer.create로 음악이 만들어졌고 여기서 Main Thread의 리소스를 많이 사용해 버벅거리는 현상이 발생했던 것이다.


해결책 1

그래서 해당 코드를 Thread로 처리해 버벅거림 현상을 해결했다.

코드를 보면

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class PlayerController {
    // ...
    public void setMusic(final Uri musicUri) {    
        // ...        
        new Thread() {            
            public void run() {
                try {
                    player.release();
                } catch (Exception e) {
 
                } finally {
                    player = null;
                }
 
                player = MediaPlayer.create(context, musicUri);
                player.setLooping(isLoop);
 
                player.setOnCompletionListener((mp) -> {
                    currentStatus = Const.ACTION_MUSIC_NEXT;
                    Log.e("heepie""finished Music");
                });
 
                play();
 
            }
        }.start();        
    // ...
    }
    // ...
}
cs

문제점 2 

이렇게 코드를 변경하니 버벅거리는 현상은 해결했다. 그러나 더 큰 문제가 발생했다. 

빠른 속도로 음악을 변경하게 될 경우, 음악이 2개가 동시에 실행되는 문제가 발생했다.

 

원인 MusicPlayer를 Release하는 부분이 있지만, Thread로 병렬로 처리되기 때문에 1개의 Thread가 완료되기 전 다음 Thread가 시작되면 이전 음악은 Release되지 않는다.


해결책 2

그래서 처리방법을 고민하면서 책과 인터넷을 찾아봤다.

그 결과, MusicPlayer를 1개의 Thread만 접근 가능한 Thread-safe한 List에 담아두고 가장 마지막에 선택된 음악을 제외하고 나머지를 Release하는 방법을 선택했다. 그림으로 확인하면

Thread-safe List의 대한 실험(?)

(Thread-safe List 실습1 - http://heepie.tistory.com/201,    

Thread-safe List 실습2 - http://heepie.tistory.com/202)

코드로 표현하면 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class PlayerController {
    // ...
    public void setMusic(final Uri musicUri) {    
        // ...        
        new Thread(() -> {            
            // 음악 등록
            player = MediaPlayer.create(context, musicUri);
            player.setLooping(isLoop);
 
            player.setOnCompletionListener((mp) -> {
                currentStatus = Const.ACTION_MUSIC_NEXT;
                Log.e("heepie""finished Music");
            });
            play();
 
            // 음악 추가
            playerList.add(player);
 
            // 마지막에 추가된 음악을 제외한 나머지는 모두 제거
            for (int i=0; i<players.size()-1; i=i+1) {
                try {
                    playerList.get(i).release();
                } catch (Exception e) {
 
                }
            }
        }).start();    
    // ...
    }
    // ...
}
cs


스크린 샷

변경 후에도 음악은 1개만 실행된다.

반영 전

반영 후

 

 

 

 

#안드로이드 음악 플레이어 #안드로이드 mp3 #안드로이드 프로젝트  #앱개발 #모바일앱개발 #어플개발

공유

댓글