-1

I have 2 ListViews. One above another. When a user clicks a row from the bottomList I am hitting a web service and creating a new cursor and repopulating the bottomList. At the same time, I want to take the clicked row and place it into the TopListView. I tried to pass an Intent to from the cursorAdapter to the MainActivity but that just repopulates the bottomListView with the same values that were there. Doesn't even make the call to the web service. Nothing happens to the TopListView.

Is it possible to pass the position of the onClick from bottomCursorAdapter to the topCursorAdapter? Or some variable like employee_number that way i can query it in the TopAdapter and swapCursor? If so, not sure how to swap cursor as there is no way to tell if someone clicked the bottomListView in the topListView.

My TopList method

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

Method I created to get the data from adapter to show toast

public void onRowClick(String mEmployeeNumber, String mFirstName) {
        Toast.makeText(getApplicationContext(), "SEND TO TOP LIST " + mEmployeeNumber + " " + mFirstName, Toast.LENGTH_LONG).show();
    }

My TopAdapter that I am trying to add the onRowClick.

public class TopListCursorAdapter extends CursorAdapter {
    public TopListCursorAdapter(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 mPayrollTitle = cursor.getString(cursor.getColumnIndexOrThrow("Payroll_title"));
        String mThumbnail = cursor.getString(cursor.getColumnIndexOrThrow("ThumbnailData"));

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

        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 v) {
                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);
                v.getContext().startActivity(mIntent);
            }
        });
    }

    public static class ViewHolder {
        TextView tvFirstName;
        TextView tvLastName;
        TextView tvTitle;
        ImageView mPeepPic;
        ImageButton mDetailsButton;
        CardView mCardView;
    }
}
Adam Gardner
  • 1,216
  • 1
  • 9
  • 21
  • Are you familiar with the concept of "callbacks"? – OneCricketeer Feb 14 '17 at 01:44
  • If not, you're essentially trying to do this. Master detail flow. https://developer.android.com/training/basics/fragments/communicating.html – OneCricketeer Feb 14 '17 at 01:45
  • Does this have to be done with Fragments? The classes with my onClick events are CursorAdapters. I am not able to override the onAttach method within a CursorAdapter. – Adam Gardner Feb 14 '17 at 01:55
  • No no, just the "on interaction" interface. It's called "a callback". You already know about setOnClickListener, right? Same idea. Define your own "setclicked" method in the adapter, set it from the Activity where you have access to both adapters – OneCricketeer Feb 14 '17 at 14:35
  • I have updated my code as I am getting a null on my Callback. http://stackoverflow.com/q/42218529/4219444 Any help would be greatly appreciated. – Adam Gardner Feb 14 '17 at 15:21

1 Answers1

2

If I understand correctly, you want to have the code know when a click event happens in one adapter, and then send some data to the other one.

In that case, you can simply define an interface that bridges the "communication" between adapters through the Activity class that contains both.

For example, here is your adapter with an interface defined. It gets activated when you click the button.

public class TopListCursorAdapter extends CursorAdapter {

    public interface TopListClickListener {
        void onTopListClick(int position); // Can add more parameters here
    }

    private TopListClickListener callback;

    public TopListCursorAdapter(Context context, Cursor cursor) {
        super(context, cursor, 0);
        if (!(context instanceof TopListClickListener)) {
            throw new ClassCastException("Context must implement TopListClickListener");
        }
        this.callback = (TopListClickListener) context;
    }

    ...

        holder.mDetailsButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cursor.moveToPosition(position);
                ...
                if (callback != null) {
                    callback.onTopListClick(position); // Can pass more parameters here
                }

And in the Activity, you can implement that interface (aka your callback)

public class MainActivity extends AppCompatActivity 
    implements TopListCursorAdapter.TopListClickListener // see here

    // private ... topAdapter, bottomAdapter;

    @Override
    public void onTopListClick(int position) {
        // Make sure parameters match the interface ^^^


        // TODO: Get data from topAdapter
        // TODO: database update or arraylist.add to change bottomAdapter
        bottomAdapter.notifyDataSetChanged(); // Update the UI
    }

    // Other code can remain the same
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • Would I send the data to the other adapter the same way I would if it was a Fragment? Just calling Adapter and not Fragment in the method in MainActivity? Trying to pass all the row information on that click and send it to the other adapter to add it to the list there. – Adam Gardner Feb 14 '17 at 17:41
  • The other Fragment would need to be attached to the Activity, but I don't see why that wouldn't work. – OneCricketeer Feb 14 '17 at 17:43
  • Regarding "pass all the row information". You can create a single `Employee` object. And you could also `implement Parcelable` on that. But, you shouldn't be passing each individual field through the method. – OneCricketeer Feb 14 '17 at 17:44
  • Is there a better method for handling passing a clicked row in one adapter and adding it to another listview that belongs to a different CursorAdapter? – Adam Gardner Feb 14 '17 at 17:44
  • I know that example is for Fragments, but those aren't really "necessary" for what you are trying to accomplish. The Fragment simple encapsulates the logic of the adapters and moves it away from the Activity. – OneCricketeer Feb 14 '17 at 17:47
  • So put the rows data into an object, pass that to MainActivity, then to other adapter to add it as a new row to the list? – Adam Gardner Feb 14 '17 at 17:50
  • That's the gist of my answer yes :) – OneCricketeer Feb 14 '17 at 17:52
  • In my example, I used `topAdapter.getItem(position);`, but you could pass the `Cursor` directly, or some `Employee` object, like I said – OneCricketeer Feb 14 '17 at 17:54
  • I see you're calling the .add method for one of the adapters but the CursorAdapter doesn't have a .add method. Did you declare them as ArrayLists? – Adam Gardner Feb 14 '17 at 19:17
  • It's a method of `ArrayAdapter`, and this code is just an example, not to be taken literally. Like I commented, "database update or whatever". You can reset the Cursor of a CursorAdapter, for example. – OneCricketeer Feb 14 '17 at 19:18
  • Ok thank you, just really confused on where to go from here. Back to Google search. – Adam Gardner Feb 14 '17 at 19:20
  • Is it actually possible to pass the Cursor from the adapter back to the MainActivity? You said not to pass each field back. I am not seeing anything on how to pass this back to the MainActivity then To another CursorAdapter to populate a new row in that list. Man this feature is stupid hard. – Adam Gardner Feb 14 '17 at 19:36
  • I only say not to pass each field because then your Interface method is stupid long :) For example `cursor.moveToPosition(position); Employee e = new Employee(); e.setID(cursor.getInt(0)); callback.onTopListClick(e);`... It's pretty simple that `callback` piece. – OneCricketeer Feb 14 '17 at 19:38
  • So I threw a toast and was able to get the object when I try to pass it to bottomAdapter I am getting null on the bottomAdapter. I tried to set it to the CursorAdapter but wants a cursor when I am trying to pass it an object. Would I convert the Object to a cursor then pass that through bottomAdapter.notifyDataSetChanged()? – Adam Gardner Feb 14 '17 at 20:59
  • I'm having a difficult time understanding what you are trying to do. Can you [ask another question](//stackoverflow.com/questions/ask)?. If you can Toast the object, then it isn't null. If your buttom adapter is a Cursor adapter, you should not pass anything to it. You can `UPDATE` or `INSERT` on the database. For that, you want `ContentValues`, not a `Cursor`. – OneCricketeer Feb 14 '17 at 21:20