【问题标题】:Update UI from CursorAdapter onClick从 CursorAdapter onClick 更新 UI
【发布时间】:2017-02-07 23:39:38
【问题描述】:

我有一个 listView,当用户单击 cardView 时,我正在从与该职位相关联的 employeeNumber 调用 Web 服务。我从 OkHttp3s enqueue 中获取了新的 Web 服务调用 onResponse 的数据。如何更新 listView 以填充响应中的新数据?

真的迷路了,因为我知道 listView 正在使用进行点击的适配器。所以不知道如何调用listView,在响应完成后填充适配器。

我的 MainActivity 填充了第一个 ListView 并附加了适配器。

public class MainActivity extends AppCompatActivity {

    private ProgressBar mProgressBar;
    EmployeeDBHandler dbHandler;
    private int mStartingEmployeeID = myStartingID;
    private String table = "employees";
    private static final String DATABASE_NAME = "OneTeam";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
        dbHandler = new EmployeeDBHandler(getApplicationContext());
        mProgressBar.setVisibility(View.VISIBLE);
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

        getXMLData();

        //GUI for seeing android SQLite Database in Chrome Dev Tools
        Stetho.InitializerBuilder inBuilder = Stetho.newInitializerBuilder(this);
        inBuilder.enableWebKitInspector(Stetho.defaultInspectorModulesProvider(this));
        Stetho.Initializer in = inBuilder.build();
        Stetho.initialize(in);
    }

    public void getXMLData() {
        OkHttpClient client = getUnsafeOkHttpClient();
        Request request = new Request.Builder()
                .url(getString(R.string.API_FULL_URL))
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                final String responseData = response.body().string();
                final InputStream stream = new ByteArrayInputStream(responseData.getBytes());
                final XMLPullParserHandler parserHandler = new XMLPullParserHandler();
                final ArrayList<Employee> employees = (ArrayList<Employee>) parserHandler.parse(stream);

                for (Employee e : employees) {
                     dbHandler.addEmployee(e);

                }

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mProgressBar.setVisibility(View.GONE);
                        displayTopList();
                        displayBottomList();
                    }
                });
            }
        });
    }

    public void displayTopList() {
        SQLiteDatabase db = dbHandler.getWritableDatabase();
        Cursor mTopListCursor = db.rawQuery("SELECT * FROM " + table + " WHERE " + "Employee_number" + "=" + mStartingEmployeeID, null);
        ListView mTopListView = (ListView) findViewById(R.id.mTopList);
        TopListCursorAdapter topAdapter = new TopListCursorAdapter(this, mTopListCursor);
        mTopListView.setAdapter(topAdapter);
    }

    public void displayBottomList() {
        SQLiteDatabase db = dbHandler.getWritableDatabase();
        Cursor mBottomListCursor = db.rawQuery("SELECT * FROM " + table + " WHERE " + "Employee_number" + "!=" + mStartingEmployeeID, null);

        ListView mBottomListView = (ListView) findViewById(R.id.mDirectReportList);
        BottomListViewAdapter bottomAdapter = new BottomListViewAdapter(this, mBottomListCursor);
        mBottomListView.setAdapter(bottomAdapter);
    }

    @Override
    public void onBackPressed() {
        moveTaskToBack(false);
    }
}

具有按钮 onClick 的 CursorAdapter

public class BottomListViewAdapter extends CursorAdapter {

    private String mEmployeeNumber;
    private EmployeeDBHandler dbHandler;

    public BottomListViewAdapter(Context context, Cursor cursor) {
        super(context, cursor, 0);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return LayoutInflater.from(context).inflate(R.layout.contact_cardview_layout, parent, false);
    }

    @Override
    public void bindView(View view, final Context context, final Cursor cursor) {
        ViewHolder holder;
        holder = new ViewHolder();
        holder.tvFirstName = (TextView) view.findViewById(R.id.personFirstName);
        holder.tvLastName = (TextView) view.findViewById(R.id.personLastName);
        holder.tvTitle = (TextView) view.findViewById(R.id.personTitle);
        holder.mPeepPic = (ImageView) view.findViewById(R.id.person_photo);
        holder.mDetailsButton = (ImageButton) view.findViewById(R.id.fullDetailButton);
        holder.mCardView = (CardView) view.findViewById(R.id.home_screen_cardView);

        String mFirstName = cursor.getString(cursor.getColumnIndexOrThrow("First_name"));
        String mLastName = cursor.getString(cursor.getColumnIndexOrThrow("Last_name"));
        String mTitle = cursor.getString(cursor.getColumnIndexOrThrow("Payroll_title"));
        String mThumbnail = cursor.getString(cursor.getColumnIndexOrThrow("ThumbnailData"));

        holder.tvFirstName.setText(mFirstName);
        holder.tvLastName.setText(mLastName);
        holder.tvTitle.setText(mTitle);

        if (mThumbnail != null) {
            byte[] imageAsBytes = Base64.decode(mThumbnail.getBytes(), Base64.DEFAULT);
            Bitmap parsedImage = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length);
            holder.mPeepPic.setImageBitmap(parsedImage);
        } else {
            holder.mPeepPic.setImageResource(R.drawable.img_place_holder_adapter);
        }

        final int position = cursor.getPosition();

        holder.mDetailsButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                cursor.moveToPosition(position);
                String mEmployeeNumber = cursor.getString(1);
                String mEmail = cursor.getString(8);
                String mFirstName = cursor.getString(2);
                String mLastName = cursor.getString(3);
                String mPhoneMobile = cursor.getString(4);
                String mPhoneOffice = cursor.getString(5);
                String mCostCenter = cursor.getString(10);
                String mHasDirectReports = cursor.getString(7);
                String mTitle = cursor.getString(6);
                String mPic = cursor.getString(9);
                Intent mIntent = new Intent(context, EmployeeFullInfo.class);
                mIntent.putExtra("Employee_number", mEmployeeNumber);
                mIntent.putExtra("Email", mEmail);
                mIntent.putExtra("First_name", mFirstName);
                mIntent.putExtra("Last_name", mLastName);
                mIntent.putExtra("Phone_mobile", mPhoneMobile);
                mIntent.putExtra("Phone_office", mPhoneOffice);
                mIntent.putExtra("Cost_center_id", mCostCenter);
                mIntent.putExtra("Has_direct_reports", mHasDirectReports);
                mIntent.putExtra("Payroll_title", mTitle);
                mIntent.putExtra("ThumbnailData", mPic);
                mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                view.getContext().startActivity(mIntent);
            }
        });

        holder.mCardView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cursor.moveToPosition(position);
                mEmployeeNumber = cursor.getString(1);
                Toast.makeText(context, mEmployeeNumber, Toast.LENGTH_SHORT).show();
                dbHandler = new EmployeeDBHandler(context);
                callNewDirectReport();

            }
        });
    }

    public static class ViewHolder {
        TextView tvFirstName;
        TextView tvLastName;
        TextView tvTitle;
        ImageView mPeepPic;
        ImageButton mDetailsButton;
        CardView mCardView;
    }

    private void callNewDirectReport() {
        String mDirectReportUrl = "https://b2aproxy.supervalu.com/OneTeam/OneTeamService.asmx/GetDirectReportsWithPicture";

        HttpUrl.Builder urlBuilder = HttpUrl.parse(mDirectReportUrl).newBuilder();
        urlBuilder.addQueryParameter("manager_employee_number", mEmployeeNumber);
        String url = urlBuilder.build().toString();


        OkHttpClient client = getUnsafeOkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                    final String responseData = response.body().string();
                    final InputStream stream = new ByteArrayInputStream(responseData.getBytes());
                    final XMLPullParserHandler parserHandler = new XMLPullParserHandler();
                    final ArrayList<Employee> employees = (ArrayList<Employee>) parserHandler.parse(stream);

                    for (Employee e : employees) {
                        dbHandler.addEmployee(e);
                    }


            }
        });
    }
}

【问题讨论】:

  • 是否有可能在更新数据库之前更新适配器?
  • 我不这样做。我可以但不确定这如何帮助 onClick 方法使用新响应更新 UI。
  • 我试图理解:基本上,您想根据底层数据库的变化来更新 UI,对吧?你考虑过装载机吗?
  • @Valentino S. 我需要在 CursorAdapter 中创建 LoaderManager 还是需要创建另一个类来处理这个问题?我一直在看一些指南,但我正在努力思考如何实现加载器以在调用 Web 服务后更新 UI。
  • 我只是想给你一个有用的答案

标签: android listview android-cursoradapter


【解决方案1】:

也许您可以尝试使用Loaders

它们让您将数据源(内容提供者或其他)与活动或片段绑定。当加载器处于活动状态时,它们应该监控数据的来源并在内容发生变化时提供新的结果。

我将为您提供如何实现它们的一般方法(尤其是 CursorLoader)。我希望清楚:

public class MainActivity extends AppCompatActivity implements
    LoaderManager.LoaderCallbacks<Cursor> {

    private static final int LOADER_INTEGER = 1;

    // ... existing code

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        getLoaderManager().initLoader(LOADER_INTEGER, null, this);
        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        return new CursorLoader(
            this,
            ContentProvider.CONTENT_URI,
            projection,
            null,
            null,
            sortOrder
        );
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        mCursorAdapter.swapCursor(cursor);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        mCursorAdapter.swapCursor(null);
    }
}

您可以在互联网上阅读很多关于此的内容,例如here 是一个好的开始。

希望这会有所帮助!

【讨论】:

  • 对 CONTENT_URI 和项目应该是什么有点困惑。此外,当从 Web 服务接收到新数据时,这如何与按钮单击相关联。
  • 你有一个内容提供者来与你的 SQLite 数据库交互吗?
  • 我没有,我知道我需要一个。我去了你提供的链接,但现在看到有一个指南可以帮助设置装载机。我会努力解决这个问题,希望不需要任何帮助,如果我会提出另一个问题。谢谢。
  • 我看到解释不清楚,我还以为你有一个内容提供者,但感谢你接受答案!有什么不清楚的可以随便问,我尽量回答:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多