PreferenceFragment가 호환성 패키지에서 의도적으로 제외 되었습니까?


153

3.0 및 3.0 이전 장치 모두에 적용 할 수있는 환경 설정을 작성하려고합니다. PreferenceActivity더 이상 사용되지 않는 메소드 가 포함되어 있음을 발견 한 경우 (동봉 된 샘플 코드에서 사용되지만) PreferenceFragement문제를 해결하기 위해 호환성 패키지를 살펴 보았습니다 .

그러나 PreferenceFragment호환성 패키지에없는 것으로 보입니다 . 누구든지 이것이 의도적인지 말해 줄 수 있습니까? 그렇다면 다양한 기기를 쉽게 타겟팅 할 수 있습니까 (예 : <3.0 및> = 3.0) 후프를 뛰어 넘어야합니까? 의도적으로 제외되지 않은 경우 호환성 패키지의 새로운 릴리스를 기대할 수 있습니까? 또는 사용하기에 안전한 다른 해결 방법이 있습니까?

건배

제임스


1
이것은 문제를 해결하기위한 나의 접근법이다 : stackoverflow.com/questions/14076073/…
ecv

누군가 PreferenceFragment가 당신이 잊어 버릴 제 3자를 만들었 습니다. 내 답변을 참조하십시오 .
theblang

Chris Banes 는 자신의 블로그에 대한 의견 으로이 문제 해결합니다 . 그는 그 이유는 다음과 같다고 말했다"Because most of Preferences' implementation is hidden, therefore impossible to backport without lots of hackery."
theblang

업데이트 된 답변을 참조하십시오 . PreferenceFragmentCompat최근 지원 라이브러리에 추가되었습니다.
theblang

답변:


90

PreferenceActivity에 더 이상 사용되지 않는 메소드가 포함되어 있음을 발견 (이는 첨부 된 샘플 코드에서 사용됨)

더 이상 사용되지 않는 메소드는 Android 3.0부터 더 이상 사용되지 않습니다. 모든 Android 버전에서 완벽하게 작동하지만 PreferenceFragmentAndroid 3.0 이상 에서 사용 하는 것이 좋습니다 .

누구든지 이것이 의도적인지 말해 줄 수 있습니까?

내 생각 엔 엔지니어링 시간의 문제이지만 그것은 추측 일뿐입니다.

그렇다면 다양한 기기를 쉽게 타겟팅 할 수 있습니까 (예 : <3.0 및> = 3.0) 후프를 뛰어 넘어야합니까?

나는 그것이 "쉽게"행해진다고 생각한다. PreferenceActivity하나는 기본 설정 헤더를 PreferenceFragments사용하고 다른 하나는 원래 접근 방식을 사용하는 두 가지 별도의 구현이 있습니다. 필요한 시점 (예 : 사용자가 옵션 메뉴 항목을 클릭 할 때)에서 올바른 것을 선택하십시오. 이것을 보여주는 샘플 프로젝트가 있습니다. 또는 이 샘플 프로젝트PreferenceActivity 에서와 같이 두 경우를 모두 처리 하는 싱글 을 보유하십시오 .

의도적으로 제외되지 않은 경우 호환성 패키지의 새로운 릴리스를 기대할 수 있습니까?

당신은 우리의 나머지 사람들이 언제, 언제 배송하는지 알아낼 것입니다.

또는 사용하기에 안전한 다른 해결 방법이 있습니까?

위 참조.


건배 마크. 나는 당신이 몇 곳 (Google 그룹과 블로그)에서 이것에 대해 의견을 말했지만 명확한 대답을 원했습니다 (상황이 주어질 수있는 한).
James

@ 제임스 : 예, 환경 설정 XML로 확실하게 <include>작동 하지 않기 때문에 문지름은 환경 설정 XML 정의에 있으며 조각으로 잘 작동하고 함께 연결되는 것을 얻습니다 . BTW, 구독자 인 경우이 프로젝트를 참조하는 도서 업데이트가 몇 분 전에 발표되었습니다.
CommonsWare

7
죄송합니다. 여기에서 어떤 점을 만들려고했는지 잘 모르겠습니다. 전혀 대답하지 않고 문제와 관련이없는 관련없는 외부 링크를 언급 / 추측 / 참조합니다. PreferenceFragment의 호환성 버전이 없으면 생략이 의도적인지 아닌지에 대한 문제는 PreferenceFragment가 존재하지 않으면 getSupportFragmentManager () 또는 다른 메소드 중 어느 것도 수행하지 않기 때문에 설명 된 방식으로 PreferenceActivity를 확장 할 수있는 방법이 없습니다 처음에는 조각을 사용해야합니다.
저스틴

8
@JustinBuser : "질문이 의도적 인 것인지 아닌지에 대한 의문이 있습니다."-Google에서 일할 수있는 유일한 사람들입니다. Google에서 구직 활동을 시작해보십시오. "설명한 방법으로 PreferenceActivity를 확장 할 수있는 방법이 없습니다"– 내가 링크 한 코드를 다운로드해도됩니다.
CommonsWare

9
@JustinBuser 기록을 위해 Mark는 내 질문에 대답했습니다. 그의 대답을 받아들이는 것이 분명합니다.
제임스

21

@CommonsWare의 대답의 미묘한 의미는 앱이 호환성 API 또는 내장 조각 API (SDK 11 이후부터) 중에서 선택해야한다는 것입니다. 실제로 "쉽게"권장 사항이 수행 한 것입니다. 즉, PreferenceFragment를 사용하려면 앱에서 기본 제공 단편 API를 사용하고 PreferenceActivity에서 더 이상 사용되지 않는 메소드를 처리해야합니다. 반대로, 앱이 compat을 사용하는 것이 중요하다면. API PreferenceFragment 클래스가 전혀 없을 때 직면하게 될 API입니다. 따라서 장치 타겟팅은 문제가되지 않지만 하나 또는 다른 API를 선택하여 예기치 않은 해결 방법으로 디자인을 제출해야 할 때 후프 점핑이 발생합니다. 나는 동료가 필요하다. API를 사용하여 PreferenceFragment 클래스를 직접 만들고 작동 방식을 살펴 보겠습니다. 최악의 시나리오에서 나는

편집 : http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/preference/PreferenceFragment.java 에서 코드를보고 시도한 후 ? av = h- 내 자신의 PreferenceFragment를 만들 수 없습니다. 기본 설정은 'protected'대신 PreferenceManager에서 package-private를 자유롭게 사용하는 것으로 보입니다. 실제로 보안이나 동기 부여가없는 것처럼 보이지 않으며 단위 테스트에는 좋지 않지만 아쉽게 입력합니다.

편집 v2 : 실제로 발생했고 작동했습니다. 호환성 API JAR로 코드를 작동시키는 것은 분명히 골치 아픈 일이었습니다. com.android.preference 패키지를 SDK에서 내 앱으로 약 70 % 복사 한 다음 일반적으로 Android에서 평범한 품질의 Java 코드로 씨름했습니다. SDK v14를 사용했습니다. 일부 Android 엔지니어가이 주제에 대해 말한 것과는 달리 Goog 엔지니어는 내가 한 일을 훨씬 쉽게 수행 할 수있었습니다.

BTW- "타겟팅 장치가 문제가되지 않는다"고 말했습니까? com.android.preference를 사용하면 주요 리팩토링없이 호환성 API로 교체 할 수 없습니다. 재미있는 로그!


좀 더 직접하겠습니다. 관심있는 모든 것이 Honeycomb 이상을 목표로하고 있다면 (시장 점유율이 어느 정도입니까?) @Commonsware의 답변에 투표하십시오! 오늘날 시장에 나와있는 대부분의 Android 기기에 관심이 있다면 내 답변을 읽어야합니다.
Tenacious

4
이 작업을 수행 한 방법을 기꺼이 공유 하시겠습니까? 나는 정확히 같은 문제로 실행 해요, 단지 내 PreferenceActivity를 로더를 사용하기 때문에 내가 가지고 있어야 호환성 라이브러리를 사용합니다.
Karakuri

3
@Tenacious 나는 당신의 조사를 좋아합니다-잘했습니다. 그러나 누군가가 첫 번째 의견에 레코드를 똑바로 설정해야한다고 생각합니다 .Commonsware의 코드는 사전 및 사후 HC 장치에서 작동합니다. 알아야 할 것은 런타임에 이전 장치를 지원하기 위해 사용되는 후기 바인딩입니다. 런타임시 버전 확인은 두 가지 OS 제품군을 모두 지원합니다. 이것은 일반적인 Android 패턴입니다 (내가 좋아하는 것이 아니라 Android 개발자가 배우고 익숙해지기 위해 중요한 것입니다). 두 가지 접근법을 모두 무시하지 마십시오.
Richard Le Mesurier

@RichardLeMesurier하지만 Commonsware의 방법을 사용하면 DrawerLayout 내부 환경 설정이 필요하면 적절한하지 않습니다
neworld

16

CommonsWare의 답변과 Tenacious의 관찰을 바탕으로 최소한의 번거 로움없이 코드 또는 리소스 중복없이 모든 현재 Android API 버전을 대상으로 할 수있는 단일 하위 클래스 솔루션을 고안했습니다. PreferenceActivity Android 4.0 및 이전 버전 의 관련 질문에 대한 답변을 참조하십시오

또는 내 블로그 : http://www.blackmoonit.com/2012/07/all_api_prefsactivity/

4.0.3 및 4.0.4를 실행하는 두 태블릿과 4.0.4 및 2.3.3을 실행하는 전화기와 1.6을 실행하는 에뮬레이터에서 테스트되었습니다.



10

2015 년 8 월 Google은 새로운 환경 설정 지원 라이브러리 v7을 출시했습니다 .

이제 사용할 수 있습니다 PreferenceFragmentCompat을 하나와 ActivityAppCompatActivity

public static class PrefsFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.preferences);
    }
}

preferenceTheme테마 를 설정 해야합니다.

<style name="AppTheme" parent="@style/Theme.AppCompat.Light">
  ...
  <item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
</style>

이러한 방식으로 preferenceTheme활동의 다른 부분에 영향을 미치지 않고 각 환경 설정 유형에 사용되는 레이아웃 스타일을 사용자 정의 할 수 있습니다 .


1
나는 당신이 함수를 그리워한다고 생각합니다 : onCreatePreferences
Android 개발자

이것은 나의 하루를 구했다! Android Studio의 프로젝트 구조에서 왜 이것이 보이지 않는지 궁금합니다 ... ?? BTW 코드에 오타가 있습니다. "PreferenceFragmentCompat 확장"
Grzegorz D.

7

Tenacious의 답변은 정확하지만 자세한 내용은 다음과 같습니다.

"일반 레이아웃을 작성하고보기 컴포넌트를 sharedprefs에 수동으로 바인드 할 수없는"이유는 android.preferences API에 놀라운 부분이 없기 때문입니다. PreferenceActivity 및 PreferenceFragment는 모두 중요하지 않은 비공개 PreferenceManager 메소드에 액세스 할 수 있으며 사용자 고유의 환경 설정 UI를 구현할 수 없습니다.

특히, XML 파일에서 Preference 계층을 구성하려면 PreferenceManager를 사용해야하지만 모든 PreferenceManager의 생성자는 모두 패키지 전용이거나 숨겨져 있습니다. Preference onClick 리스너를 활동에 첨부하는 방법도 패키지 전용입니다.

Android API의 비공개 메소드는 실제로 SDK에서 생략되므로 구현을 android.preferences 패키지에 숨기면이 문제를 해결할 수 없습니다. 리플렉션 및 다이내믹 프록시와 관련된 약간의 창의력을 가지고 있으면서도 계속 사용할 수 있습니다. Tenacious가 말한 유일한 대안은 15 개 이상의 클래스, 5 개의 레이아웃, 비슷한 수의 style.xml 및 attrs.xml 요소를 포함하여 전체 android.preference 패키지를 포크하는 것입니다.

따라서 원래 질문에 답하기 위해 Google이 PreferenceFragment를 호환성 패키지에 포함시키지 않은 이유는 Tenacious 및 나와 동일한 어려움을 겪었 기 때문입니다. 구글조차도 시간을 거슬러 올라가서 이전 플랫폼에서 그 방법을 공개 할 수 없습니다 (차후 릴리스에서 그렇게하기를 바랍니다).


2

내 애플의 목표는 API +14하지만 일부 멋진 탐색을위한 지원 라이브러리를 사용하기 때문에, 내가 사용하지 수 android.app.Fragment사용하고 있었다를 android.support.v4.app.Fragment, 그러나 나는 또한이 필요 PreferenceFragment코드 뒤에에 큰 변화없이 자리에.

그래서 지원 라이브러리의 세계와 PreferenceFragment:

private android.support.v4.app.Fragment fragment;
private android.app.Fragment nativeFragment = null;

private void selectItem(int position) {
    fragment = null;
    boolean useNativeFragment = false;
    switch (position) {
    case 0:
        fragment = new SampleSupprtFragment1();
        break;
    case 1:
        fragment = new SampleSupprtFragment2();
        break;
    case 2:
        nativeFragment = new SettingsFragment();
        useNativeFragment = true;
        break;
    }
    if (useNativeFragment) {
        android.app.FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.beginTransaction()
            .replace(R.id.content_frame, nativeFragment).commit();
    } else {
        if (nativeFragment != null) {
            getFragmentManager().beginTransaction().remove(nativeFragment)
                .commit();
            nativeFragment = null;
        }
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
            .replace(R.id.content_frame, fragment).commit();
    }
}

2

기본 설정을 응용 프로그램 디자인에 통합하고 2.3 안드로이드를 계속 지원해야했습니다. 그래서 여전히 PreferencesFragment가 필요했습니다.

일부 검색 후 android-support-v4-preferencefragment lib를 발견했습니다. 이 lib는 Tenacious가 말한 것처럼 원래 PreferencesFragment를 복사하고 리팩토링하는 데 많은 시간을 절약합니다. 잘 작동하고 사용자는 환경 설정을 즐길 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.