fragment가 저절로 공유되는 현상


메인엑티비티 에 4개의 프래그먼트를 만들었습니다.

첫번째 프래그먼트(가장왼쪽 프래그먼트)의 onCreateView 함수에 ProgressDialog를 넣어, 첫번째 프래그먼트가 보여질 때 로딩이 되는 것같은 다이얼로그를 잠시 띄워줍니다.

프래그먼트 생명주기대로라면 첫 번째 프래그먼트를 벗어나고 다시 첫 번째 프래그먼트로 진입하면 이 다이얼로그가 보여져야합니다.

그런데 세 번째 혹은 네 번째 프래그먼트(가장 오른쪽 프래그먼트)까지 갔다가, 두 번째 프래그먼트를 진입할 때, 이 로딩되는 것같은 다이얼로그가 생깁니다.

마치 두 번째 프래그먼트가 첫 번째 프래그먼트와 공유되는것 같습니다..

밤을새서 그런지 비몽사몽하지만 코드를 아무리 뒤져봐도 문제는 없는 것 같습니다..

//////////첫 번째 프래그먼트 코드
////////////////////////////////

public class Fragment1 extends Fragment implements WeatherServiceCallback{

    private ImageView weatherIconImageView;
    private TextView temperatureTextView;
    private TextView conditionTextView;
    private TextView locationTextView;

    private YahooWeatherService service;
    private ProgressDialog dialog; //로딩중 다이얼로그

    TextView tv;
    ToggleButton tb;
    Button updateBtn; // 날씨 업뎃 버튼
    LocationManager lm;

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment1, container, false);

        weatherIconImageView = (ImageView)v.findViewById(R.id.weatherIconImageView);
        temperatureTextView = (TextView)v.findViewById(R.id.temperatureTextView);
        conditionTextView = (TextView)v.findViewById(R.id.conditionTextView);
        locationTextView = (TextView)v.findViewById(R.id.locationTextView);

        // Location 제공자에서 정보를 얻어오기(GPS)
        // 1. Location을 사용하기 위한 권한을 얻어와야한다 AndroidManifest.xml
        //     ACCESS_FINE_LOCATION : NETWORK_PROVIDER, GPS_PROVIDER
        //     ACCESS_COARSE_LOCATION : NETWORK_PROVIDER
        // 2. LocationManager 를 통해서 원하는 제공자의 리스너 등록
        // 3. GPS 는 에뮬레이터에서는 기본적으로 동작하지 않는다
        // 4. 실내에서는 GPS_PROVIDER 를 요청해도 응답이 없다.  특별한 처리를 안하면 아무리 시간이 지나도
        //    응답이 없다.
        //    해결방법은
        //     ① 타이머를 설정하여 GPS_PROVIDER 에서 일정시간 응답이 없는 경우 NETWORK_PROVIDER로 전환
        //     ② 혹은, 둘다 한꺼번헤 호출하여 들어오는 값을 사용하는 방식.

        tv = (TextView)v.findViewById(R.id.textView2);
        tv.setText("위치정보 미수신중");

        tb = (ToggleButton)v.findViewById(R.id.toggle1);

        // LocationManager 객체를 얻어온다
        lm = (LocationManager)getActivity().getSystemService(Context.LOCATION_SERVICE);

        updateBtn = (Button) v.findViewById(R.id.updateButton);

        updateBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try{
                        tv.setText("수신중..");
                        // GPS 제공자의 정보가 바뀌면 콜백하도록 리스너 등록하기~!!!
                        lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, // 등록할 위치제공자
                                100, // 통지사이의 최소 시간간격 (miliSecond)
                                1, // 통지사이의 최소 변경거리 (m)
                                mLocationListener);
                        lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, // 등록할 위치제공자
                                100, // 통지사이의 최소 시간간격 (miliSecond)
                                1, // 통지사이의 최소 변경거리 (m)
                                mLocationListener);

                }catch(SecurityException ex){
                }
            }
        });

        service = new YahooWeatherService(this);
        service.refreshWeather("Soeul, SouthKorea"); //지역이름으로 날씨서비스 시작

        dialog = new ProgressDialog(getActivity());
        dialog.setMessage("Loading...");
        dialog.show();

        return v;

    }

    @Override  //YahooWeatherService 오버라이드
    public void serviceSuccess(Channel channel) {
        dialog.hide();

        Item item = channel.getItem();

        //JSON파일 내에서 code값 추출하기
        int resourceId = getResources().getIdentifier("drawable/icon_" + item.getCondition().getCode()
                , null, getActivity().getPackageName());

        @SuppressWarnings("deprecation")  //code값에 맞는 drawable 대입
                Drawable weatherIconDrawable = getResources().getDrawable(resourceId);

        //code값에 맞는(상황에 맞는) 날씨 이미지뷰로 셋
        weatherIconImageView.setImageDrawable(weatherIconDrawable);

        temperatureTextView.setText(item.getCondition().getTemperature() + "\u00B0 " + channel.getUnits().getTemperature());
        conditionTextView.setText(item.getCondition().getDescription());
        locationTextView.setText(service.getLocation());

    }

    @Override  //YahooWeatherService 오버라이드
    public void serviceFailure(Exception exception) {
        dialog.hide();
        Toast.makeText(getActivity(), exception.getMessage(), Toast.LENGTH_LONG).show();
    }

    private final LocationListener mLocationListener = new LocationListener() {

        public void onLocationChanged(Location location) {
            //여기서 위치값이 갱신되면 이벤트가 발생한다.
            //값은 Location 형태로 리턴되며 좌표 출력 방법은 다음과 같다.

            Log.d("test", "onLocationChanged, location:" + location);
            double longitude = location.getLongitude(); //경도
            double latitude = location.getLatitude();   //위도
            double altitude = location.getAltitude();   //고도
            float accuracy = location.getAccuracy();    //정확도
            String provider = location.getProvider();   //위치제공자
            //Gps 위치제공자에 의한 위치변화. 오차범위가 좁다.
            //Network 위치제공자에 의한 위치변화
            //Network 위치는 Gps에 비해 정확도가 많이 떨어진다.
            tv.setText("위치정보 : " + provider + "\n위도 : " + longitude + "\n경도 : " + latitude
                    + "\n고도 : " + altitude + "\n정확도 : "  + accuracy);

            try{  //  미수신할때는 반드시 자원해체를 해주어야 한다.
                lm.removeUpdates(mLocationListener);
            } catch (SecurityException ex){

            }
        }
        public void onProviderDisabled(String provider) {
            // Disabled시
            Log.d("test", "onProviderDisabled, provider:" + provider);
        }

        public void onProviderEnabled(String provider) {
            // Enabled시
            Log.d("test", "onProviderEnabled, provider:" + provider);
        }

        public void onStatusChanged(String provider, int status, Bundle extras) {
            // 변경시
            Log.d("test", "onStatusChanged, provider:" + provider + ", status:" + status + " ,Bundle:" + extras);
        }
    };

}



//////////////////////두 번째 프래그먼트 코드
////////////////////////////////////////////

public class Fragment2 extends Fragment {

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View v = inflater.inflate(R.layout.fragment2, container, false);

        return v;

    }
}



//////////////////////// Fragment들이 속한 MainActivity 코드
/////////////////////////////////////////////////////////////

public class MainActivity extends AppCompatActivity {

    private SectionsPagerAdapter mSectionsPagerAdapter;

    /**
     * The {@link ViewPager} that will host the section contents.
     */
    private ViewPager mViewPager;
    private SimpleSideDrawer mSlidingMenu;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        //위치데이터를 사용하기 위해서는 사용자로부터 permission 사용 여부를 확인 받아야 함
        if ( ContextCompat.checkSelfPermission( MainActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) {

            ActivityCompat.requestPermissions( MainActivity.this, new String[] {  android.Manifest.permission.ACCESS_FINE_LOCATION  }, CONTEXT_INCLUDE_CODE );
        }

        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.container);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(mViewPager);

        mSlidingMenu = new SimpleSideDrawer(this); //슬라이드 메뉴 라이브러리 생성
        mSlidingMenu.setLeftBehindContentView(R.layout.slide_menu);

        ImageButton slide_btn = (ImageButton)findViewById(R.id.slide_btn); //슬라이드 메뉴 생성 버튼
        slide_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mSlidingMenu.toggleLeftDrawer();

                ImageView profileImage = (ImageView)findViewById(R.id.profileImage);
                TextView name = (TextView)findViewById(R.id.name);
                TextView email = (TextView)findViewById(R.id.email);

                Intent intent = getIntent();
                String profileEmail = intent.getExtras().getString("email");
                String profileName = intent.getExtras().getString("name");
                Bundle b = intent.getExtras();
                Bitmap bm = (Bitmap)b.get("profileImage");

                profileImage.setImageBitmap(bm);
                name.setText("이름 "+profileName);
                email.setText("이메일 "+profileEmail);

            }
        });

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            if (position == 0)
                return new Fragment1();
            else if(position==1)
                return new Fragment2();
            else if(position==2)
                return new Fragment3();
            else
                return new Fragment4();
            }

        @Override
        public int getCount() {
            // Show 4 total pages.
            return 4;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            switch (position) {
                case 0:
                    return "날씨";
                case 1:
                    return "자연재해";
                case 2:
                    return "범죄";
                case 3:
                    return "설정";
            }
            return null;
        }
    }


}

두 번째 프래그먼트는 아무런 코드를 입력하지 않았는데도 이럽니다..


  • activity에 관련된 소스가 있어야 확실히 알겠지만 증상만 봤을때는 viewpager를 사용하시는것 같네요. viewpager의 경우 현재의 fragment외에 옆의 fragment도 instance를 생성합니다. activity의 내용을 확인해보세요 사견이지만...oncreateview보다 onattach를 사용해보시는것도 방법일것 같네요...    로빈퀸   2016.11.4 15:22     
  • 메인액티비티 소스를 추가했는데 혹시 봐주실 수 있나요?..    Jun Yong Lee   2016.11.4 20:25     
조회수 107


1 답변


좋아요
1
싫어요
채택취소하기

앞서 말씀드린 내용처럼 viewpager를 사용하셨네요 viewpager는 성능향상을 위해 page가 넘어가려는 화면을 미리 Loading 해놓습니다. 그래서 1page의 화면이 display된다고 해도 2page의 화면을 미리 만들어 놓는것이지요 마찬가지로 2페이지에 있을때는 유저의 동작이 1페이지와 3페이지 어느 부분을 이동할지 알수가 없으니 1페이지와 3페이지를 모두 미리 만들어 놓습니다. 로딩하려는 페이지의 갯수는 소스상으로 컨트롤 가능합니다.

미리 페이지 로딩을 막는 방법이 있는데 아래 링크 참조하시면 될것 같습니다. http://stackoverflow.com/questions/10073214/viewpager-setoffscreenpagelimit0-doesnt-work-as-expected

다만 page로딩을 미리 해놓지 못한 상태에서 swipe 동작으로 다음 페이지 넘어갈시 움직임에 끊김이 있을 수 있습니다. 그래서 사용자입장으로 봤을때 그리 좋지 않은 동작이므로 추천드리진 않습니다.

  • 2016년 11월 04일에 작성됨

로그인이 필요한 기능입니다.

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 작성한 답변에 다른 개발자들이 댓글을 작성하거나 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.
► 로그인
► 계정만들기
Close