如何将我的AutoCompleteTextView方法/适配器移动到自己的类

时间:2017-02-03 21:43:01

标签: java android android-adapter

我试图将一些方法从我的登录活动中移到一个单独的类中,以便其他活动可以重用它们。我无法弄清楚,并希望根据我在下面的用法提供一些示例。

Thnx提前。

LoginActivity.java:

public class LoginActivity extends FirebaseUserNet implements LoaderManager.LoaderCallbacks<Cursor> {


    public AutoCompleteTextView inputEmail;

    /**
     * Id to identity READ_CONTACTS permission request.
     */
    public static final int REQUEST_READ_CONTACTS = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

    inputEmail = (AutoCompleteTextView) findViewById(R.id.email);

    // Populate the users contacts with their given permission
        populateAutoComplete();

    }

    /**
      * TODO: Everything below here needs to be put into a separate class(s) for reuse:
      */

    public void populateAutoComplete() {
        if (!mayRequestContacts()) {
            return;
        }

        getSupportLoaderManager().initLoader(0, null, this);
    }

    public boolean mayRequestContacts() {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            return true;
        }
        if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
            return true;
        }
        if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
            Snackbar.make(inputEmail, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
                    .setAction(android.R.string.ok, new View.OnClickListener() {
                        @Override
                        @TargetApi(Build.VERSION_CODES.M)
                        public void onClick(View v) {
                            requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
                        }
                    });
        } else {
            requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
        }
        return false;
    }

    /**
     * Callback received when a permissions request has been completed.
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
                                           @NonNull int[] grantResults) {
        if (requestCode == REQUEST_READ_CONTACTS) {
            if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                populateAutoComplete();
            }
        }
    }

    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
        return new CursorLoader(this,
                // Retrieve data rows for the device user's 'profile' contact.
                ContactsContract.Data.CONTENT_URI, ProfileQueryInterface.PROJECTION,

                // Select only email addresses.
                ContactsContract.Contacts.Data.MIMETYPE +
                        " = ?", new String[]{ContactsContract.CommonDataKinds.Email
                .CONTENT_ITEM_TYPE},

                // Show primary email addresses first. Note that there won't be
                // a primary email address if the user hasn't specified one.
                ContactsContract.Contacts.Data.IS_PRIMARY + " DESC");
    }

    public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
        List<String> emails = new ArrayList<>();
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            emails.add(cursor.getString(ProfileQueryInterface.ADDRESS));
            cursor.moveToNext();
        }

        addEmailsToAutoComplete(emails);
    }

    public void onLoaderReset(Loader<Cursor> cursorLoader) {

    }

    private void addEmailsToAutoComplete(List<String> emailAddressCollection) {
        //Create adapter to tell the AutoCompleteTextView what to show in its dropdown list.
        ArrayAdapter<String> adapter =
                new ArrayAdapter<>(LoginActivity.this,
                        android.R.layout.simple_dropdown_item_1line, emailAddressCollection);

        inputEmail.setAdapter(adapter);
    }

3 个答案:

答案 0 :(得分:0)

你可以理论上提取所有公共方法,它们不会覆盖它们各自的超类方法。那将是

public void populateAutoComplete()

public boolean mayRequestContacts()

public Loader<Cursor> onCreateLoader(int i, Bundle bundle)

public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor)

public void onLoaderReset(Loader<Cursor> cursorLoader)

private void addEmailsToAutoComplete(List<String> emailAddressCollection)

我会添加参数

LoginActivity log_act

到每个方法,所以你可以给方法一个

this

指向类Instance的指针。 这样,方法仍然可以访问类中的所有内容,例如字段

public AutoCompleteTextView inputEmail;

或类似

的方法
getSupportLoaderManager().initLoader(0, null, this);

答案 1 :(得分:0)

实际上,您可以使用CursorAdapter删除所有Loader内容,但无论如何

首先,我提取出&#34;可能会要求&#34;方法。

public interface ContactPermissionRequester {
    boolean mayRequestContacts();
}

让您的活动实现这一点。

然后,我们的想法是你只想进行一个裸骨活动并自我包含自动完成文本视图。为此,至少需要Context和TextView。对于数据库Loader,您也传递了它。

您需要在活动中询问这些方法的权限我认为

  • checkSelfPermission
  • shouldShowRequestPermissionRationale
  • requestPermissions

你可以尝试给另一个类ContextCompat而不是Context,看看你是否可以移动权限逻辑。

public class LoginActivity extends FirebaseUserNet implements ContactPermissionRequester {

    @Override
    public boolean mayRequestContacts() {
        ...
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, 
        @NonNull int[] grantResults) {
            ...
        }

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        inputEmail = (AutoCompleteTextView) findViewById(R.id.email);
        AutoCompleteTextViewLoader autoloader = new AutoCompleteTextViewLoader(this, 
            inputEmail, getSupportLoaderManager());
        autoloader.populate();

    }
}

几乎所有其他内容都可以拉入新类,并在必要时使用适当的参数/字段。 Activity现在只是一个Context,但它也实现了可以请求权限的早期接口。

public class AutoCompleteTextViewLoader implements LoaderManager.LoaderCallbacks<Cursor> {

    private final Context mContext;
    private final AutoCompleteTextView inputEmail;
    private final ArrayAdapter<String> adapter;
    private final LoaderManager loaderManager

    private final List<String> emails = new ArrayList<>();

    private final ContactPermissionRequester requester;

    public AutoCompleteLoader(Context context, AutoCompleteTextView textView, LoaderManager loaderManager) {
        this.mContext = context;

        this.inputEmail = textView;
        this.adapter = new ArrayAdapter<>(mContext,
                    android.R.layout.simple_dropdown_item_1line,      
                    emails);
        this.inputEmail.setAdapter(adapter);

        // This can throw a ClassCastException
        this.mRequester = (ContactPermissionRequester) context;

        this.loaderManager = loaderManager;
    }

    public List<String> getEmails() { return emails; }

    public void populate() {
        if (requester != null && !requester.mayRequestContacts()) {
            return;
        }

        loadManager.initLoader(0, null, this);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
        return new CursorLoader(mContext,
                // Retrieve data rows for the device user's 'profile' contact.
                ContactsContract.Data.CONTENT_URI, ProfileQueryInterface.PROJECTION,

                // Select only email addresses.
                ContactsContract.Contacts.Data.MIMETYPE +
                        " = ?", new String[]{ContactsContract.CommonDataKinds.Email
                .CONTENT_ITEM_TYPE},

                // Show primary email addresses first. Note that there won't be
                // a primary email address if the user hasn't specified one.
                ContactsContract.Contacts.Data.IS_PRIMARY + " DESC");
    }

    @Override
    public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
        // ArrayList not needed here
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            // Add directly to adapter
            adapter.add(cursor.getString(ProfileQueryInterface.ADDRESS));
            cursor.moveToNext();
        }
        // Separate method was pointless
    }

    @Override
    public void onLoaderReset(Loader<Cursor> cursorLoader) {

    }
}

答案 2 :(得分:0)

关于如何提取方法[只是一个数组适配器]的答案@cricket_007 gave is correct。但对于那些希望实际代码有效的人,我在下面有说明并处理构建版本&gt; = API level 23所需的权限请求,蛇形图和对话框,我还实现了Google's easypermissions

在活动中:

public class SomeActivity implements EasyPermissions.PermissionCallbacks {
    . . .
    /**
      * Id to identity READ_CONTACTS permission request.
      */
    public static int REQUEST_READ_CONTACTS = 0;

    @Override
        protected void onCreate(Bundle savedInstanceState) {
        . . .
        //TODO: Fire `mayRequestContacts()` when the `AutoCompleteTextView` has focus.
        mayRequestContacts();
        . . .
    }

    public void mayRequestContacts() {
        String[] perms = { Manifest.permission.READ_CONTACTS };
        if (EasyPermissions.hasPermissions(this, perms)) {
            // Have permission, do the thing!
        } else {
            // Ask for permissions
            EasyPermissions.requestPermissions(this, getString(R.string.agreement_positive_text),
                    REQUEST_READ_CONTACTS, perms);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        // Forward results to EasyPermissions
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

    @Override
    public void onPermissionsGranted(int requestCode, List<String> perms) {

        if (requestCode == REQUEST_READ_CONTACTS) {
            AutoCompleteTextViewLoader autoCompleteTextViewLoader = new AutoCompleteTextViewLoader(this,
                        inputEmail, getSupportLoaderManager());
            autoCompleteTextViewLoader.populate();
        }
    }

    @Override
    public void onPermissionsDenied(int requestCode, List<String> perms) {

        if (requestCode == REQUEST_READ_CONTACTS) {
            Toast.makeText(this, "Sorry you choose that - You\'ll be typing a lot more.", Toast.LENGTH_SHORT).show();
        }
    }

}

<强> AutoCompleteTextEmailLoader:

public class AutoCompleteTextEmailLoader implements LoaderManager.LoaderCallbacks<Cursor> {

    private final Context mContext;
    private final AutoCompleteTextView inputEmail;
    private final ArrayAdapter<String> adapter;
    private final LoaderManager loaderManager;
    private final List<String> emails = new ArrayList<>();

    public AutoCompleteTextEmailLoader(Context context, AutoCompleteTextView textView, LoaderManager loaderManager) {
        this.mContext = context;

        this.inputEmail = textView;
        this.adapter = new ArrayAdapter<>(mContext,
                android.R.layout.simple_dropdown_item_1line,
                emails);
        this.inputEmail.setAdapter(adapter);
        this.loaderManager = loaderManager;
    }

    public void populate() {
        loaderManager.initLoader(0, null, this);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
        return new CursorLoader(mContext,
                // Retrieve data rows for the device user's 'profile' contact.
                ContactsContract.Data.CONTENT_URI, ProfileQueryInterface.PROJECTION,

                // Select only email addresses.
                ContactsContract.Contacts.Data.MIMETYPE +
                        " = ?", new String[]{ContactsContract.CommonDataKinds.Email
                .CONTENT_ITEM_TYPE},

                // Show primary email addresses first. Note that there won't be
                // a primary email address if the user hasn't specified one.
                ContactsContract.Contacts.Data.IS_PRIMARY + " DESC");
    }

    @Override
    public void onLoadFinished(Loader<Cursor> cursorLoader, Cursor cursor) {
        // ArrayList not needed here
        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
            // Add directly to adapter
            adapter.add(cursor.getString(ProfileQueryInterface.ADDRESS));
            cursor.moveToNext();
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> cursorLoader) {
    }
}