Sử dụng cái gì thay thế cho addPreferencesFromResource trực tiếp trong PreferenceActivity?


360

Tôi chỉ nhận thấy thực tế là phương pháp addPreferencesFromResource(int preferencesResId)này được đánh dấu không dùng nữa trong tài liệu của Android ( Tham khảo mục nhập ).

Thật không may, không có phương pháp thay thế nào được cung cấp trong mô tả của phương pháp.

Phương thức nào nên được sử dụng thay thế để kết nối một ưu tiênScreen.xml với PreferenceActivity phù hợp?


2
Một cách tiếp cận rất đơn giản được cung cấp bởi WannaGetHigh tại stackoverflow.com/questions/23523806/
Sabin

Các giải pháp ở đó vẫn sử dụng addPreferencesFromResource(int preferencesResId). Tui bỏ lỡ điều gì vậy ?
Jammo

@Jammo Có nhưng nó đã được chuyển từ Activity sang Fragment để phản ánh cách làm mới -> đoạn.
WannaGetHigh

Câu trả lời:


332

Không có phương pháp thay thế nào được cung cấp trong mô tả của phương thức vì cách tiếp cận ưa thích (như API cấp 11) là khởi tạo các đối tượng PreferenceFragment để tải tùy chọn của bạn từ tệp tài nguyên. Xem mã mẫu tại đây: PreferenceActivity


Cảm ơn bạn rất nhiều vì câu trả lời của bạn. Tôi chỉ đang làm theo các hướng dẫn không được chấp nhận từ "Phát triển Video2Brain-Android" dẫn tôi đến việc sử dụng phiên bản phương pháp của PreferenceActivity. Btw: Tôi rất thích đánh giá câu trả lời của bạn là hữu ích nếu tôi chỉ có thể.
mweisz

33
Bây giờ chỉ khi PreferenceFragment được bao gồm trong gói tương thích thì việc sử dụng nó stackoverflow.com/questions/5501431/
trộm

1
Vì tôi sử dụng Action Bar Sherlock, tôi đã theo dõi blog sau để giải quyết vấn đề này, xem ... commonsware.com/blog/2012/10/16/ chủ đề
Ai đó ở đâu đó vào

2
Tuy nhiên, bạn cần gọi addPreferencesFromResource (int PreferencesID) nếu bạn muốn ứng dụng tương thích ngược với mức api trước đó hơn 11 (Android 3.0). Nhưng tôi đoán bạn cũng có thể xem xét những thiết bị cũ đó cũng bị bắt chước.
Einar Sundgren

5
@EinarSundgren Tôi là chủ sở hữu Nexus One và phiên bản tối đa có sẵn của tôi là 2.2: bạn sẽ không ngăn tôi! Tôi sẽ KHÔNG BAO GIỜ bị phản đối! Bằng sức mạnh của Grayskull ... Tôi có sức mạnh!
TechNyquist

186

Để thêm thông tin vào câu trả lời đúng ở trên, sau khi đọc một ví dụ từ Android-er tôi thấy bạn có thể dễ dàng chuyển đổi hoạt động tùy chọn của mình thành một đoạn ưu tiên. Nếu bạn có hoạt động sau:

public class MyPreferenceActivity extends PreferenceActivity
{
    @Override
    protected void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.my_preference_screen);
    }
}

Những thay đổi duy nhất bạn phải thực hiện là tạo một lớp phân đoạn bên trong, di chuyển addPreferencesFromResources()vào đoạn đó và gọi đoạn từ hoạt động, như thế này:

public class MyPreferenceActivity extends PreferenceActivity
{
    @Override
    protected void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        getFragmentManager().beginTransaction().replace(android.R.id.content, new MyPreferenceFragment()).commit();
    }

    public static class MyPreferenceFragment extends PreferenceFragment
    {
        @Override
        public void onCreate(final Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.my_preference_screen);
        }
    }
}

Có thể có sự tinh tế khác để thực hiện các ưu tiên phức tạp hơn từ các mảnh; Nếu vậy, tôi hy vọng ai đó lưu ý chúng ở đây.


6
Tốt đẹp, cảm ơn vì điều này. Java và kiểu suy nghĩ này đã bị loại bỏ khỏi thế giới .net nhỏ bé xinh đẹp của tôi :)
Tom

44
Tại sao họ lại mất giá addPreferencesFromResources()trong giao dịch cho PreferenceFragment? Có vẻ không cần thiết từ quan điểm người mới bắt đầu.
Howdy_McGee

4
Cuộc gọi yêu cầu API cấp 11
mehmet

1
Vậy nếu API ở cấp 9 thì sao? @mehmet
gumuruh

2
Câu trả lời tuyệt vời! Có cách nào để đạt được điều này mà không thay đổi android.R.id.content? dường như không phù hợp với tôi vì một số lý do ... (sửa tôi nếu tôi sai)
tomer.z

37

@Garret Wilson Cảm ơn bạn rất nhiều! Là một người không biết gì về mã hóa Android, tôi đã bị mắc kẹt với vấn đề không tương thích về sở thích trong nhiều giờ và tôi thấy thật đáng thất vọng khi họ không tán thành việc sử dụng một số phương pháp / phương pháp cho các phương pháp mới không được API cũ hỗ trợ phải dùng đến tất cả các cách giải quyết để làm cho ứng dụng của bạn hoạt động trong một loạt các thiết bị. Thật là bực bội!

Lớp học của bạn rất tuyệt, vì nó cho phép bạn tiếp tục làm việc trong các API mới với các tùy chọn như trước đây, nhưng nó không tương thích ngược. Vì tôi đang cố gắng tiếp cận một loạt các thiết bị, tôi đã sửa đổi nó một chút để làm cho nó hoạt động trong các thiết bị API 11 trước cũng như trong các API mới hơn:

import android.annotation.TargetApi;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;

public class MyPrefsActivity extends PreferenceActivity
{
    private static int prefs=R.xml.myprefs;

    @Override
    protected void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        try {
            getClass().getMethod("getFragmentManager");
            AddResourceApi11AndGreater();
        } catch (NoSuchMethodException e) { //Api < 11
            AddResourceApiLessThan11();
        }
    }

    @SuppressWarnings("deprecation")
    protected void AddResourceApiLessThan11()
    {
        addPreferencesFromResource(prefs);
    }

    @TargetApi(11)
    protected void AddResourceApi11AndGreater()
    {
        getFragmentManager().beginTransaction().replace(android.R.id.content,
                new PF()).commit();
    }

    @TargetApi(11)
    public static class PF extends PreferenceFragment
    {       
        @Override
        public void onCreate(final Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(MyPrefsActivity.prefs); //outer class
            // private members seem to be visible for inner class, and
            // making it static made things so much easier
        }
    }
}

Đã thử nghiệm trong hai trình giả lập (2.2 và 4.2) với thành công.

Tại sao mã của tôi trông rất nhảm nhí:

Tôi là một người không biết gì về mã hóa Android và tôi không phải là người hâm mộ java tuyệt vời nhất.

Để tránh cảnh báo không dùng nữa và buộc Eclipse phải cho phép tôi biên dịch, tôi đã phải dùng đến các chú thích, nhưng dường như chúng chỉ ảnh hưởng đến các lớp hoặc phương thức, vì vậy tôi phải chuyển mã sang hai phương thức mới để tận dụng lợi thế này.

Tôi không muốn phải viết id tài nguyên xml của mình hai lần bất cứ khi nào tôi sao chép và dán lớp cho PreferenceActivity mới, vì vậy tôi đã tạo một biến mới để lưu trữ giá trị này.

Tôi hy vọng điều này sẽ hữu ích cho người khác.

Tái bút: Xin lỗi vì những quan điểm đầy quan điểm của tôi, nhưng khi bạn đến mới và tìm thấy những khuyết tật như vậy, bạn không thể làm gì ngoài việc nản lòng!


Oh well ... Tôi chỉ nhận thấy rằng tôi phải thay đổi tên lớp bên ngoài hai lần bất cứ khi nào tôi sao chép và dán nó. Thực sự có một cách để tránh điều này, bằng cách chuyển các prefs đến innerclass. Bạn không thể tạo một hàm tạo lớp bên trong chấp nhận prefs làm tham số vì rõ ràng nó không được khuyến nghị cho các lớp dẫn xuất PreferenceFragment. Ngoài ra, bạn không thể tạo một phương thức trong lớp bên trong để nhận prefs và gọi addPreferencesFromResource ngay lập tức, vì addPreferencesFromResource cần được gọi sau khi super.onCreate được gọi và onCreate không được gọi ngay sau khi lớp dẫn xuất PreferenceFragment ...
NXT

... đã được khởi tạo. Vì vậy, bạn cần tạo một biến mới trong lớp bên trong, tạo một phương thức thiết lập công khai cho nó trong lớp bên trong, để lại addPreferencesFromResource, nơi nó nằm sau lệnh gọi super.onCreate, bên trong onCreate, khởi tạo lớp bên trong, đặt các prefs và sử dụng nó trong lệnh gọi getFragmentManager () ... như trước đây.
NXT

2
Mã của bạn đã là cứu cánh !! Tôi đã cố gắng nhắm mục tiêu cả điện thoại cũ và mới, và lãng phí 3 ngày..Và câu trả lời rất đơn giản. Cảm ơn
Devdatta Tengshe

22

Cách tiếp cận của tôi rất gần với Garret Wilson (cảm ơn, tôi đã bình chọn cho bạn;)

Ngoài ra, nó cung cấp khả năng tương thích hướng xuống với Android <3.

Tôi chỉ nhận ra rằng giải pháp của tôi thậm chí còn gần với giải pháp của Kevin Remo . Nó chỉ là một trình dọn dẹp nhỏ hơn một chút (vì nó không dựa vào antipotype "expection" ).

public class MyPreferenceActivity extends PreferenceActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
            onCreatePreferenceActivity();
        } else {
            onCreatePreferenceFragment();
        }
    }

    /**
     * Wraps legacy {@link #onCreate(Bundle)} code for Android < 3 (i.e. API lvl
     * < 11).
     */
    @SuppressWarnings("deprecation")
    private void onCreatePreferenceActivity() {
        addPreferencesFromResource(R.xml.preferences);
    }

    /**
     * Wraps {@link #onCreate(Bundle)} code for Android >= 3 (i.e. API lvl >=
     * 11).
     */
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private void onCreatePreferenceFragment() {
        getFragmentManager().beginTransaction()
                .replace(android.R.id.content, new MyPreferenceFragment ())
                .commit();
    }
}

Đối với một ví dụ "thực" (nhưng phức tạp hơn), xem NusicPreferencesActivityNusicPreferencesFragment .


@SuppressLint("NewApi")- tránh - chính xác hơn. Bạn đã chạy nó cho apis thấp? Nó sẽ némVerifyError
Mr_and_Mrs_D 25/12/13

Tôi kiểm tra phần trên trên trình giả lập chạy API cấp 10, APK được xây dựng bằng SDK Phiên bản 19. Bạn đã sử dụng phiên bản SDK nào để xây dựng? Cấp API thiết bị nào bạn đã chạy nó trên? Bạn đã chạy nó trên trình giả lập hoặc trên một thiết bị vật lý? Khi nào chính xác xảy ra lỗi? Nếu Ur xây dựng với SDK <= 16, hãy xem phản hồi này .
schnatterer

Bạn đang thiếu điểm - và thêm @Mr_and_Mrs_D nếu bạn muốn tôi được thông báo. Đối với VE đọc tại đây: stackoverflow.com/questions/20271593/ ,. Các @SuppressLint("NewApi")chỉ là phong cách xấu
Mr_and_Mrs_D

@M Vậy thì, một đề xuất về cách tránh @SuppressLint("NewApi")trong tình huống cụ thể này thì sao?
kẻ lừa đảo

@TargetApi(Build.VERSION_CODES.HONEYCOMB)- không phải tất cả các cảnh báo cho bất kỳ api nào :)
Mr_and_Mrs_D

6

Thay vì ngoại lệ, chỉ cần sử dụng:

if (Build.VERSION.SDK_INT >= 11)

Và sử dụng

@SuppressLint("NewApi")

để đàn áp các cảnh báo.


1
bởi vì nó không làm gì khác hơn là sụp đổ: D
Ishtiaq

1
nếu nó bị sập ... thì hãy thử và bắt nó: D
gumuruh

0

Thay vì sử dụng a PreferenceActivityđể tải trực tiếp tùy chọn, hãy sử dụng một AppCompatActivityhoặc tương đương tải một PreferenceFragmentCompattải tải tùy chọn của bạn. Đó là một phần của thư viện hỗ trợ (nay là Android Jetpack) và cung cấp khả năng tương thích trở lại API 14.

Trong của bạn build.gradle, thêm một phụ thuộc cho thư viện hỗ trợ ưu tiên:

dependencies {
    // ...
    implementation "androidx.preference:preference:1.0.0-alpha1"
}

Lưu ý: Chúng tôi sẽ cho rằng bạn đã tạo XML tùy chọn của mình.

Đối với hoạt động của bạn, tạo một lớp hoạt động mới. Nếu bạn đang sử dụng các chủ đề vật chất, bạn nên mở rộng AppCompatActivity, nhưng bạn có thể linh hoạt với điều này:

public class MyPreferencesActivity extends AppCompatActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_preferences_activity)
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.fragment_container, MyPreferencesFragment())
                    .commitNow()
        }
    }
}

Bây giờ là phần quan trọng: tạo một đoạn tải các tùy chọn của bạn từ XML:

public class MyPreferencesFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.my_preferences_fragment); // Your preferences fragment
    }
}

Để biết thêm thông tin, hãy đọc tài liệu dành cho Nhà phát triển Android PreferenceFragmentCompat.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.