问:
Imageview not on correct row after scrolling in Recyclerview
I have an app that displays my e-mail via microsoft graph api.
Everything but 1 things i working fine so far. When the list first loads in, all info is correctly displayed, but when i scroll down, then back up. The imageview of the attachement sits on the wrong rows. It just displays on rows without attachement. In the adapter i have an if clausule which says to only show the image in the row if the hasAttachement value is "true".. I really don't get why it is redrawin the image in the wrongs rows..

The method where i set the attachement is called:
setBijlage() in MessagesAdapter

EDIT: If i click the row in my app, that row displays correctly again (gains an icon if it has attachement, and deletes it if it doesn't)

MailActivity.java

```<code>public class MailActivity extends AppCompatActivityRest implements SwipeRefreshLayout.OnRefreshListener, MessagesAdapter.MessageAdapterListener {

    private String currentFolder;
    private String currentUser;
    private List<Message> messages = new ArrayList<>();
    private RecyclerView recyclerView;
    private MessagesAdapter mAdapter;
    private SwipeRefreshLayout swipeRefreshLayout;
    private ActionModeCallback actionModeCallback;
    private ActionMode actionMode;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_mail);
        super.onCreate(savedInstanceState);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        currentFolder = getString(R.string.inbox);
        currentUser = getIntent().getStringExtra("USER_EMAIL");
        setActionBarMail(currentFolder, currentUser);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
        swipeRefreshLayout.setOnRefreshListener(this);

        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));

        actionModeCallback = new ActionModeCallback();

        // show loader and fetch messages
        swipeRefreshLayout.post(
                new Runnable() {
                    @Override
                    public void run() {
                        getAllMails(15);
                    }
                }
        );
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_search) {
            Toast.makeText(getApplicationContext(), "Search...", Toast.LENGTH_SHORT).show();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void processResponse(OutlookObjectCall outlookObjectCall, JSONObject response) {

        switch (outlookObjectCall) {
            case READUSER: {
                System.out.println("reading user");
            } break;
            case READMAIL: {
                messages.clear();

                JSONObject list = response;
                try {
                    JSONArray mails = list.getJSONArray("value");
                    Type listType = new TypeToken<List<Message>>() {
                    }.getType();
                    messages = new Gson().fromJson(String.valueOf(mails), listType);
                    for (Message message : messages) {
                        message.setColor(getRandomMaterialColor("400"));
                    }
                    System.out.println(messages.get(2).getFrom().getEmailAddress().getName());

                    mAdapter = new MessagesAdapter(this, messages, this);
                    recyclerView.setAdapter(mAdapter);

                } catch (JSONException e) {
                    e.printStackTrace();
                }

                mAdapter.notifyDataSetChanged();
                swipeRefreshLayout.setRefreshing(false);

            }
            break;
            case SENDMAIL: {
                System.out.println("Just send a mail." );
            }
        }
    }

    @Override
    public void onRefresh() {
        // swipe refresh is performed, fetch the messages again
        getAllMails(15);
    }

    @Override
    public void onIconClicked(int position) {
        if (actionMode == null) {
            actionMode = startSupportActionMode(actionModeCallback);
        }

        toggleSelection(position);
    }

    @Override
    public void onIconImportantClicked(int position) {
        // Star icon is clicked,
        // mark the message as important
        Message message = messages.get(position);
        message.setImportance("normal");
        messages.set(position, message);
        mAdapter.notifyDataSetChanged();
    }

    @Override
    public void onMessageRowClicked(int position) {
        // verify whether action mode is enabled or not
        // if enabled, change the row state to activated
        if (mAdapter.getSelectedItemCount() > 0) {
            enableActionMode(position);
        } else {
            // read the message which removes bold from the row
            Message message = messages.get(position);
            message.setIsRead("true");
            messages.set(position, message);
            mAdapter.notifyDataSetChanged();

            Toast.makeText(getApplicationContext(), "Read: " + message.getBodyPreview(), Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onRowLongClicked(int position) {
        // long press is performed, enable action mode
        enableActionMode(position);
    }

    private void enableActionMode(int position) {
        if (actionMode == null) {
            actionMode = startSupportActionMode(actionModeCallback);
        }
        toggleSelection(position);
    }

    private void toggleSelection(int position) {
        mAdapter.toggleSelection(position);
        int count = mAdapter.getSelectedItemCount();

        if (count == 0) {
            actionMode.finish();
        } else {
            actionMode.setTitle(String.valueOf(count));
            actionMode.invalidate();
        }
    }

    private class ActionModeCallback implements ActionMode.Callback {
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            mode.getMenuInflater().inflate(R.menu.menu_action_mode, menu);

            // disable swipe refresh if action mode is enabled
            swipeRefreshLayout.setEnabled(false);
            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch (item.getItemId()) {
                case R.id.action_delete:
                    // delete all the selected messages
                    deleteMessages();
                    mode.finish();
                    return true;

                default:
                    return false;
            }
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {
            mAdapter.clearSelections();
            swipeRefreshLayout.setEnabled(true);
            actionMode = null;
            recyclerView.post(new Runnable() {
                @Override
                public void run() {
                    mAdapter.resetAnimationIndex();
                    // mAdapter.notifyDataSetChanged();
                }
            });
        }
    }

    // deleting the messages from recycler view
    private void deleteMessages() {
        mAdapter.resetAnimationIndex();
        List<Integer> selectedItemPositions =
                mAdapter.getSelectedItems();
        for (int i = selectedItemPositions.size() - 1; i >= 0; i--) {
            mAdapter.removeData(selectedItemPositions.get(i));
        }
        mAdapter.notifyDataSetChanged();
    }

    private void setActionBarMail(String title, String subtitle) {
        getSupportActionBar().setTitle(title);
        getSupportActionBar().setSubtitle(subtitle);
    }

    private void getAllMails(int aantalMails) {
        swipeRefreshLayout.setRefreshing(true);
        try {
            new GraphAPI().getRequest(OutlookObjectCall.READMAIL, this, "/inbox/messages?$top=" + aantalMails);

        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private int getRandomMaterialColor(String typeColor) {
        int returnColor = Color.GRAY;
        int arrayId = getResources().getIdentifier("mdcolor_" + typeColor, "array", getPackageName());

        if (arrayId != 0) {
            TypedArray colors = getResources().obtainTypedArray(arrayId);
            int index = (int) (Math.random() * colors.length());
            returnColor = colors.getColor(index, Color.GRAY);
            colors.recycle();
        }
        return returnColor;
    }
</code>```

MessagesAdapter.java

```<code>public class MessagesAdapter extends RecyclerView.Adapter<MessagesAdapter.MyViewHolder> {
    private Context mContext;
    private List<Message> messages;
    private MessageAdapterListener listener;
    private SparseBooleanArray selectedItems;

    // array used to perform multiple animation at once
    private SparseBooleanArray animationItemsIndex;
    private boolean reverseAllAnimations = false;

    // index is used to animate only the selected row
    // dirty fix, find a better solution
    private static int currentSelectedIndex = -1;

    public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener {
        public TextView from, subject, message, iconText, timestamp;
        public ImageView iconImp, imgProfile, imgBijlage;
        public LinearLayout messageContainer;
        public RelativeLayout iconContainer, iconBack, iconFront;

        public MyViewHolder(View view) {
            super(view);
            from = (TextView) view.findViewById(R.id.from);
            subject = (TextView) view.findViewById(R.id.txt_primary);
            message = (TextView) view.findViewById(R.id.txt_secondary);
            iconText = (TextView) view.findViewById(R.id.icon_text);
            timestamp = (TextView) view.findViewById(R.id.timestamp);
            iconBack = (RelativeLayout) view.findViewById(R.id.icon_back);
            iconFront = (RelativeLayout) view.findViewById(R.id.icon_front);
            iconImp = (ImageView) view.findViewById(R.id.icon_star);
            imgProfile = (ImageView) view.findViewById(R.id.icon_profile);
            messageContainer = (LinearLayout) view.findViewById(R.id.message_container);
            iconContainer = (RelativeLayout) view.findViewById(R.id.icon_container);
            imgBijlage = (ImageView) view.findViewById(R.id.icon_attachement);
            view.setOnLongClickListener(this);
        }

        @Override
        public boolean onLongClick(View view) {
            listener.onRowLongClicked(getAdapterPosition());
            view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
            return true;
        }
    }

    public MessagesAdapter(Context mContext, List<Message> messages, MessageAdapterListener listener) {
        this.mContext = mContext;
        this.messages = messages;
        this.listener = listener;
        selectedItems = new SparseBooleanArray();
        animationItemsIndex = new SparseBooleanArray();
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.message_list_row, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        Message message = messages.get(position);

        // displaying text view data
        holder.from.setText(message.getFrom().getEmailAddress().getName());
        holder.subject.setText(message.getSubject());
        holder.message.setText(message.getBodyPreview());
        System.out.println("EMAIL: " + position + " HAS ATTACHEMENT: " + message.getHasAttachments());
        setBijlage(message, holder);
        try {
            setDate(message, holder);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        // displaying the first letter of From in icon text
        holder.iconText.setText(message.getFrom().getEmailAddress().getName().substring(0, 1));

        // change the row state to activated
        holder.itemView.setActivated(selectedItems.get(position, false));

        // change the font style depending on message read status
        applyReadStatus(holder, message);

        // handle message star
        applyImportant(holder, message);

        // handle icon animation
        applyIconAnimation(holder, position);

        // display profile image
        applyProfilePicture(holder, message);

        // apply click events
        applyClickEvents(holder, position);
    }

    private void setDate(Message message, MyViewHolder holder) throws ParseException {
        String stringDate = message.getReceivedDateTime();
        String COMPARE_FORMAT = "yyyy/MM/dd";
        String OUTPUT_FORMAT_NOT_TODAY = "dd MMM";
        String JSON_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
        SimpleDateFormat dateFormat = new SimpleDateFormat(COMPARE_FORMAT);
        SimpleDateFormat formatter = new SimpleDateFormat(JSON_FORMAT);
        SimpleDateFormat defaultFormat = new SimpleDateFormat(OUTPUT_FORMAT_NOT_TODAY);

        //today date (check if today)
        Date today = new Date();
        String currentDate = dateFormat.format(today);
        //hours (if today
        Date date = formatter.parse(stringDate);
        formatter.applyPattern(COMPARE_FORMAT);
        String mailDate = formatter.format(date);
        //dd/month (if not today)

        boolean is24 = DateFormat.is24HourFormat(mContext);

        if (mailDate.equals(currentDate)) {
            if (is24) {
                SimpleDateFormat outputFormat = new SimpleDateFormat("HH:mm");
                holder.timestamp.setText(outputFormat.format(date));
            } else {
                SimpleDateFormat outputFormat = new SimpleDateFormat("hh:mm a");
                holder.timestamp.setText(outputFormat.format(date));
            }
        } else {
            holder.timestamp.setText(defaultFormat.format(date));
        }
    }

    private void setBijlage(Message message, MyViewHolder holder){
        //set bijlage
        if (message.getHasAttachments().toLowerCase().equals("true")){
            holder.imgBijlage.setImageResource(R.drawable.ic_bijlage);
        }
    }

    private void applyClickEvents(MyViewHolder holder, final int position) {
        holder.iconContainer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onIconClicked(position);
            }
        });

        holder.iconImp.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onIconImportantClicked(position);
            }
        });

        holder.messageContainer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onMessageRowClicked(position);
            }
        });

        holder.messageContainer.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                listener.onRowLongClicked(position);
                view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
                return true;
            }
        });
    }

    private void applyProfilePicture(MyViewHolder holder, Message message) {
            holder.imgProfile.setImageResource(R.drawable.bg_circle);
            holder.imgProfile.setColorFilter(message.getColor());
            holder.iconText.setVisibility(View.VISIBLE);

    }

    private void applyIconAnimation(MyViewHolder holder, int position) {
        if (selectedItems.get(position, false)) {
            holder.iconFront.setVisibility(View.GONE);
            resetIconYAxis(holder.iconBack);
            holder.iconBack.setVisibility(View.VISIBLE);
            holder.iconBack.setAlpha(1);
            if (currentSelectedIndex == position) {
                FlipAnimator.flipView(mContext, holder.iconBack, holder.iconFront, true);
                resetCurrentIndex();
            }
        } else {
            holder.iconBack.setVisibility(View.GONE);
            resetIconYAxis(holder.iconFront);
            holder.iconFront.setVisibility(View.VISIBLE);
            holder.iconFront.setAlpha(1);
            if ((reverseAllAnimations && animationItemsIndex.get(position, false)) || currentSelectedIndex == position) {
                FlipAnimator.flipView(mContext, holder.iconBack, holder.iconFront, false);
                resetCurrentIndex();
            }
        }
    }

    // As the views will be reused, sometimes the icon appears as
    // flipped because older view is reused. Reset the Y-axis to 0
    private void resetIconYAxis(View view) {
        if (view.getRotationY() != 0) {
            view.setRotationY(0);
        }
    }

    public void resetAnimationIndex() {
        reverseAllAnimations = false;
        animationItemsIndex.clear();
    }

    @Override
    public long getItemId(int position) {
        return messages.get(position).getAutoId();
    }

    private void applyImportant(MyViewHolder holder, Message message) {
        if (message.getImportance().toLowerCase().equals("high")) {
            holder.iconImp.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_star_black_24dp));
            holder.iconImp.setColorFilter(ContextCompat.getColor(mContext, R.color.icon_tint_selected));
        } else {
            holder.iconImp.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_star_border_black_24dp));
            holder.iconImp.setColorFilter(ContextCompat.getColor(mContext, R.color.icon_tint_normal));
        }
    }

    private void applyReadStatus(MyViewHolder holder, Message message) {
        if (message.getIsRead().toLowerCase().equals("true")) {
            holder.from.setTypeface(null, Typeface.NORMAL);
            holder.subject.setTypeface(null, Typeface.NORMAL);
            holder.from.setTextColor(ContextCompat.getColor(mContext, R.color.subject));
            holder.subject.setTextColor(ContextCompat.getColor(mContext, R.color.message));
        } else {
            holder.from.setTypeface(null, Typeface.BOLD);
            holder.subject.setTypeface(null, Typeface.BOLD);
            holder.from.setTextColor(ContextCompat.getColor(mContext, R.color.from));
            holder.subject.setTextColor(ContextCompat.getColor(mContext, R.color.subject));
        }
    }

    @Override
    public int getItemCount() {
        return messages.size();
    }

    public void toggleSelection(int pos) {
        currentSelectedIndex = pos;
        if (selectedItems.get(pos, false)) {
            selectedItems.delete(pos);
            animationItemsIndex.delete(pos);
        } else {
            selectedItems.put(pos, true);
            animationItemsIndex.put(pos, true);
        }
        notifyItemChanged(pos);
    }

    public void clearSelections() {
        reverseAllAnimations = true;
        selectedItems.clear();
        notifyDataSetChanged();
    }

    public int getSelectedItemCount() {
        return selectedItems.size();
    }

    public List<Integer> getSelectedItems() {
        List<Integer> items =
                new ArrayList<>(selectedItems.size());
        for (int i = 0; i < selectedItems.size(); i++) {
            items.add(selectedItems.keyAt(i));
        }
        return items;
    }

    public void removeData(int position) {
        messages.remove(position);
        resetCurrentIndex();
    }

    private void resetCurrentIndex() {
        currentSelectedIndex = -1;
    }

    public interface MessageAdapterListener {
        void onIconClicked(int position);

        void onIconImportantClicked(int position);

        void onMessageRowClicked(int position);

        void onRowLongClicked(int position);
    }
}
</code>```

答:
Change setBijlage to this..

```<code>private void setBijlage(Message message, MyViewHolder holder){
            //set bijlage
            if (message.getHasAttachments().toLowerCase().equals("true")){
                holder.imgBijlage.setVisibility(View.VISIBLE);
                holder.imgBijlage.setImageResource(R.drawable.ic_bijlage);
            }else{
                holder.imgBijlage.setVisibility(View.GONE);
            }
        }
</code>```

Body:
I have an app that displays my e-mail via microsoft graph api.
Everything but 1 things i working fine so far. When the list first loads in, all info is correctly displayed, but when i scroll down, then back up. The imageview of the attachement sits on the wrong rows. It just displays on rows without attachement. In the adapter i have an if clausule which says to only show the image in the row if the hasAttachement value is "true".. I really don't get why it is redrawin the image in the wrongs rows..

The method where i set the attachement is called:
setBijlage() in MessagesAdapter

EDIT: If i click the row in my app, that row displays correctly again (gains an icon if it has attachement, and deletes it if it doesn't)

MailActivity.java

public class MailActivity extends AppCompatActivityRest implements SwipeRefreshLayout.OnRefreshListener, MessagesAdapter.MessageAdapterListener {

    private String currentFolder;
    private String currentUser;
    private List<Message> messages = new ArrayList<>();
    private RecyclerView recyclerView;
    private MessagesAdapter mAdapter;
    private SwipeRefreshLayout swipeRefreshLayout;
    private ActionModeCallback actionModeCallback;
    private ActionMode actionMode;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_mail);
        super.onCreate(savedInstanceState);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        currentFolder = getString(R.string.inbox);
        currentUser = getIntent().getStringExtra("USER_EMAIL");
        setActionBarMail(currentFolder, currentUser);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
        swipeRefreshLayout.setOnRefreshListener(this);

        RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));

        actionModeCallback = new ActionModeCallback();

        // show loader and fetch messages
        swipeRefreshLayout.post(
                new Runnable() {
                    @Override
                    public void run() {
                        getAllMails(15);
                    }
                }
        );
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_search) {
            Toast.makeText(getApplicationContext(), "Search...", Toast.LENGTH_SHORT).show();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void processResponse(OutlookObjectCall outlookObjectCall, JSONObject response) {

        switch (outlookObjectCall) {
            case READUSER: {
                System.out.println("reading user");
            } break;
            case READMAIL: {
                messages.clear();

                JSONObject list = response;
                try {
                    JSONArray mails = list.getJSONArray("value");
                    Type listType = new TypeToken<List<Message>>() {
                    }.getType();
                    messages = new Gson().fromJson(String.valueOf(mails), listType);
                    for (Message message : messages) {
                        message.setColor(getRandomMaterialColor("400"));
                    }
                    System.out.println(messages.get(2).getFrom().getEmailAddress().getName());

                    mAdapter = new MessagesAdapter(this, messages, this);
                    recyclerView.setAdapter(mAdapter);

                } catch (JSONException e) {
                    e.printStackTrace();
                }

                mAdapter.notifyDataSetChanged();
                swipeRefreshLayout.setRefreshing(false);

            }
            break;
            case SENDMAIL: {
                System.out.println("Just send a mail." );
            }
        }
    }

    @Override
    public void onRefresh() {
        // swipe refresh is performed, fetch the messages again
        getAllMails(15);
    }

    @Override
    public void onIconClicked(int position) {
        if (actionMode == null) {
            actionMode = startSupportActionMode(actionModeCallback);
        }

        toggleSelection(position);
    }

    @Override
    public void onIconImportantClicked(int position) {
        // Star icon is clicked,
        // mark the message as important
        Message message = messages.get(position);
        message.setImportance("normal");
        messages.set(position, message);
        mAdapter.notifyDataSetChanged();
    }

    @Override
    public void onMessageRowClicked(int position) {
        // verify whether action mode is enabled or not
        // if enabled, change the row state to activated
        if (mAdapter.getSelectedItemCount() > 0) {
            enableActionMode(position);
        } else {
            // read the message which removes bold from the row
            Message message = messages.get(position);
            message.setIsRead("true");
            messages.set(position, message);
            mAdapter.notifyDataSetChanged();

            Toast.makeText(getApplicationContext(), "Read: " + message.getBodyPreview(), Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onRowLongClicked(int position) {
        // long press is performed, enable action mode
        enableActionMode(position);
    }

    private void enableActionMode(int position) {
        if (actionMode == null) {
            actionMode = startSupportActionMode(actionModeCallback);
        }
        toggleSelection(position);
    }

    private void toggleSelection(int position) {
        mAdapter.toggleSelection(position);
        int count = mAdapter.getSelectedItemCount();

        if (count == 0) {
            actionMode.finish();
        } else {
            actionMode.setTitle(String.valueOf(count));
            actionMode.invalidate();
        }
    }

    private class ActionModeCallback implements ActionMode.Callback {
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            mode.getMenuInflater().inflate(R.menu.menu_action_mode, menu);

            // disable swipe refresh if action mode is enabled
            swipeRefreshLayout.setEnabled(false);
            return true;
        }

        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;
        }

        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            switch (item.getItemId()) {
                case R.id.action_delete:
                    // delete all the selected messages
                    deleteMessages();
                    mode.finish();
                    return true;

                default:
                    return false;
            }
        }

        @Override
        public void onDestroyActionMode(ActionMode mode) {
            mAdapter.clearSelections();
            swipeRefreshLayout.setEnabled(true);
            actionMode = null;
            recyclerView.post(new Runnable() {
                @Override
                public void run() {
                    mAdapter.resetAnimationIndex();
                    // mAdapter.notifyDataSetChanged();
                }
            });
        }
    }

    // deleting the messages from recycler view
    private void deleteMessages() {
        mAdapter.resetAnimationIndex();
        List<Integer> selectedItemPositions =
                mAdapter.getSelectedItems();
        for (int i = selectedItemPositions.size() - 1; i >= 0; i--) {
            mAdapter.removeData(selectedItemPositions.get(i));
        }
        mAdapter.notifyDataSetChanged();
    }

    private void setActionBarMail(String title, String subtitle) {
        getSupportActionBar().setTitle(title);
        getSupportActionBar().setSubtitle(subtitle);
    }

    private void getAllMails(int aantalMails) {
        swipeRefreshLayout.setRefreshing(true);
        try {
            new GraphAPI().getRequest(OutlookObjectCall.READMAIL, this, "/inbox/messages?$top=" + aantalMails);

        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    private int getRandomMaterialColor(String typeColor) {
        int returnColor = Color.GRAY;
        int arrayId = getResources().getIdentifier("mdcolor_" + typeColor, "array", getPackageName());

        if (arrayId != 0) {
            TypedArray colors = getResources().obtainTypedArray(arrayId);
            int index = (int) (Math.random() * colors.length());
            returnColor = colors.getColor(index, Color.GRAY);
            colors.recycle();
        }
        return returnColor;
    }

MessagesAdapter.java

public class MessagesAdapter extends RecyclerView.Adapter<MessagesAdapter.MyViewHolder> {
    private Context mContext;
    private List<Message> messages;
    private MessageAdapterListener listener;
    private SparseBooleanArray selectedItems;

    // array used to perform multiple animation at once
    private SparseBooleanArray animationItemsIndex;
    private boolean reverseAllAnimations = false;

    // index is used to animate only the selected row
    // dirty fix, find a better solution
    private static int currentSelectedIndex = -1;

    public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener {
        public TextView from, subject, message, iconText, timestamp;
        public ImageView iconImp, imgProfile, imgBijlage;
        public LinearLayout messageContainer;
        public RelativeLayout iconContainer, iconBack, iconFront;

        public MyViewHolder(View view) {
            super(view);
            from = (TextView) view.findViewById(R.id.from);
            subject = (TextView) view.findViewById(R.id.txt_primary);
            message = (TextView) view.findViewById(R.id.txt_secondary);
            iconText = (TextView) view.findViewById(R.id.icon_text);
            timestamp = (TextView) view.findViewById(R.id.timestamp);
            iconBack = (RelativeLayout) view.findViewById(R.id.icon_back);
            iconFront = (RelativeLayout) view.findViewById(R.id.icon_front);
            iconImp = (ImageView) view.findViewById(R.id.icon_star);
            imgProfile = (ImageView) view.findViewById(R.id.icon_profile);
            messageContainer = (LinearLayout) view.findViewById(R.id.message_container);
            iconContainer = (RelativeLayout) view.findViewById(R.id.icon_container);
            imgBijlage = (ImageView) view.findViewById(R.id.icon_attachement);
            view.setOnLongClickListener(this);
        }

        @Override
        public boolean onLongClick(View view) {
            listener.onRowLongClicked(getAdapterPosition());
            view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
            return true;
        }
    }

    public MessagesAdapter(Context mContext, List<Message> messages, MessageAdapterListener listener) {
        this.mContext = mContext;
        this.messages = messages;
        this.listener = listener;
        selectedItems = new SparseBooleanArray();
        animationItemsIndex = new SparseBooleanArray();
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.message_list_row, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(final MyViewHolder holder, final int position) {
        Message message = messages.get(position);

        // displaying text view data
        holder.from.setText(message.getFrom().getEmailAddress().getName());
        holder.subject.setText(message.getSubject());
        holder.message.setText(message.getBodyPreview());
        System.out.println("EMAIL: " + position + " HAS ATTACHEMENT: " + message.getHasAttachments());
        setBijlage(message, holder);
        try {
            setDate(message, holder);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        // displaying the first letter of From in icon text
        holder.iconText.setText(message.getFrom().getEmailAddress().getName().substring(0, 1));

        // change the row state to activated
        holder.itemView.setActivated(selectedItems.get(position, false));

        // change the font style depending on message read status
        applyReadStatus(holder, message);

        // handle message star
        applyImportant(holder, message);

        // handle icon animation
        applyIconAnimation(holder, position);

        // display profile image
        applyProfilePicture(holder, message);

        // apply click events
        applyClickEvents(holder, position);
    }

    private void setDate(Message message, MyViewHolder holder) throws ParseException {
        String stringDate = message.getReceivedDateTime();
        String COMPARE_FORMAT = "yyyy/MM/dd";
        String OUTPUT_FORMAT_NOT_TODAY = "dd MMM";
        String JSON_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
        SimpleDateFormat dateFormat = new SimpleDateFormat(COMPARE_FORMAT);
        SimpleDateFormat formatter = new SimpleDateFormat(JSON_FORMAT);
        SimpleDateFormat defaultFormat = new SimpleDateFormat(OUTPUT_FORMAT_NOT_TODAY);

        //today date (check if today)
        Date today = new Date();
        String currentDate = dateFormat.format(today);
        //hours (if today
        Date date = formatter.parse(stringDate);
        formatter.applyPattern(COMPARE_FORMAT);
        String mailDate = formatter.format(date);
        //dd/month (if not today)

        boolean is24 = DateFormat.is24HourFormat(mContext);

        if (mailDate.equals(currentDate)) {
            if (is24) {
                SimpleDateFormat outputFormat = new SimpleDateFormat("HH:mm");
                holder.timestamp.setText(outputFormat.format(date));
            } else {
                SimpleDateFormat outputFormat = new SimpleDateFormat("hh:mm a");
                holder.timestamp.setText(outputFormat.format(date));
            }
        } else {
            holder.timestamp.setText(defaultFormat.format(date));
        }
    }

    private void setBijlage(Message message, MyViewHolder holder){
        //set bijlage
        if (message.getHasAttachments().toLowerCase().equals("true")){
            holder.imgBijlage.setImageResource(R.drawable.ic_bijlage);
        }
    }

    private void applyClickEvents(MyViewHolder holder, final int position) {
        holder.iconContainer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onIconClicked(position);
            }
        });

        holder.iconImp.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onIconImportantClicked(position);
            }
        });

        holder.messageContainer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                listener.onMessageRowClicked(position);
            }
        });

        holder.messageContainer.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                listener.onRowLongClicked(position);
                view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
                return true;
            }
        });
    }

    private void applyProfilePicture(MyViewHolder holder, Message message) {
            holder.imgProfile.setImageResource(R.drawable.bg_circle);
            holder.imgProfile.setColorFilter(message.getColor());
            holder.iconText.setVisibility(View.VISIBLE);

    }

    private void applyIconAnimation(MyViewHolder holder, int position) {
        if (selectedItems.get(position, false)) {
            holder.iconFront.setVisibility(View.GONE);
            resetIconYAxis(holder.iconBack);
            holder.iconBack.setVisibility(View.VISIBLE);
            holder.iconBack.setAlpha(1);
            if (currentSelectedIndex == position) {
                FlipAnimator.flipView(mContext, holder.iconBack, holder.iconFront, true);
                resetCurrentIndex();
            }
        } else {
            holder.iconBack.setVisibility(View.GONE);
            resetIconYAxis(holder.iconFront);
            holder.iconFront.setVisibility(View.VISIBLE);
            holder.iconFront.setAlpha(1);
            if ((reverseAllAnimations && animationItemsIndex.get(position, false)) || currentSelectedIndex == position) {
                FlipAnimator.flipView(mContext, holder.iconBack, holder.iconFront, false);
                resetCurrentIndex();
            }
        }
    }

    // As the views will be reused, sometimes the icon appears as
    // flipped because older view is reused. Reset the Y-axis to 0
    private void resetIconYAxis(View view) {
        if (view.getRotationY() != 0) {
            view.setRotationY(0);
        }
    }

    public void resetAnimationIndex() {
        reverseAllAnimations = false;
        animationItemsIndex.clear();
    }

    @Override
    public long getItemId(int position) {
        return messages.get(position).getAutoId();
    }

    private void applyImportant(MyViewHolder holder, Message message) {
        if (message.getImportance().toLowerCase().equals("high")) {
            holder.iconImp.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_star_black_24dp));
            holder.iconImp.setColorFilter(ContextCompat.getColor(mContext, R.color.icon_tint_selected));
        } else {
            holder.iconImp.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_star_border_black_24dp));
            holder.iconImp.setColorFilter(ContextCompat.getColor(mContext, R.color.icon_tint_normal));
        }
    }

    private void applyReadStatus(MyViewHolder holder, Message message) {
        if (message.getIsRead().toLowerCase().equals("true")) {
            holder.from.setTypeface(null, Typeface.NORMAL);
            holder.subject.setTypeface(null, Typeface.NORMAL);
            holder.from.setTextColor(ContextCompat.getColor(mContext, R.color.subject));
            holder.subject.setTextColor(ContextCompat.getColor(mContext, R.color.message));
        } else {
            holder.from.setTypeface(null, Typeface.BOLD);
            holder.subject.setTypeface(null, Typeface.BOLD);
            holder.from.setTextColor(ContextCompat.getColor(mContext, R.color.from));
            holder.subject.setTextColor(ContextCompat.getColor(mContext, R.color.subject));
        }
    }

    @Override
    public int getItemCount() {
        return messages.size();
    }

    public void toggleSelection(int pos) {
        currentSelectedIndex = pos;
        if (selectedItems.get(pos, false)) {
            selectedItems.delete(pos);
            animationItemsIndex.delete(pos);
        } else {
            selectedItems.put(pos, true);
            animationItemsIndex.put(pos, true);
        }
        notifyItemChanged(pos);
    }

    public void clearSelections() {
        reverseAllAnimations = true;
        selectedItems.clear();
        notifyDataSetChanged();
    }

    public int getSelectedItemCount() {
        return selectedItems.size();
    }

    public List<Integer> getSelectedItems() {
        List<Integer> items =
                new ArrayList<>(selectedItems.size());
        for (int i = 0; i < selectedItems.size(); i++) {
            items.add(selectedItems.keyAt(i));
        }
        return items;
    }

    public void removeData(int position) {
        messages.remove(position);
        resetCurrentIndex();
    }

    private void resetCurrentIndex() {
        currentSelectedIndex = -1;
    }

    public interface MessageAdapterListener {
        void onIconClicked(int position);

        void onIconImportantClicked(int position);

        void onMessageRowClicked(int position);

        void onRowLongClicked(int position);
    }
}

Body:
Change setBijlage to this..

private void setBijlage(Message message, MyViewHolder holder){
            //set bijlage
            if (message.getHasAttachments().toLowerCase().equals("true")){
                holder.imgBijlage.setVisibility(View.VISIBLE);
                holder.imgBijlage.setImageResource(R.drawable.ic_bijlage);
            }else{
                holder.imgBijlage.setVisibility(View.GONE);
            }
        }


来源: stackexchange

问:
PowerApps merge related tables
I'm new to PowerApps and am exploring relational databases before starting a project in PowerApps (involving relational databases). I'm trying to do a simple join of two entities (drink and human), where the drink has a BuyerID field which relates to a "human"'s Primary ID.
So I tried
ForAll(Filter(drink, (name = "Americano") And (drink.BuyerID = human.PrimaryId) ), Collect(AmericanoDrinkers, {FirstName: human.firstName, LastName: human.lastName}))
to get a collection of humans who brought an Americano, but I get an Invalid argument type error with drink.BuyerID = human.PrimaryId.
Any ideas? I've tried changing = to in and stuff like drink.BuyerID to drink[@BuyerID]. Note that the drink.BuyerID datatype is "Lookup" and human.PrimaryId is integer, so could I be getting this error because of the different types? Also I'm certain there's nothing wrong with the data because when editting the drink entity in excel, the powerapps add-on shows the related humans when a BuyerID is selected.

答: The problem was just the setup, I just created a new field (BuyerID2) in the drinks entity and set it as a number value rather than a lookup like BuyerID was, and all 3 (my initial one, and the two Meneghino provided) solutions worked fine (although I had to change drink.BuyerID = human.PrimaryId to BuyerID2 in human.PrimaryId).

ContentLicense: CC BY-SA 3.0

Title: PowerApps merge related tables


问:
Temporarily storing Images on elastic beanstalk api
I have a PHP API that will be hosted on Elastic Beanstalk. The user uploads images to this API. Once the API gets it, in PHP I store the file in a temp folder, then resize it to multiple sizes then upload it to an S3 Bucket.

It works locally but I haven't put this live yet. Is this possible to do once it is on an elastic beanstalk instance? I know I have to give write permissions to the temp_image directory when I work with it locally so do I have to do this when it's live on elastic beanstalk? If so, how do I manage folder directories on an elastic beanstalk? And will I have to do this every time I update my API?

Another solution I thought of is having a temp_image S3 Bucket and working from that?

Any suggestions would be great thanks!

答:
ElasticBeanstalk deployments are considered immutable post-deployment, so you will probably have to change permissions on your temp folder. Thankfully, doing so is pretty straightforward. The mechanism for performing operations such as chmod or chown is through configuration files, described here. ElasticBeanstalk configuration files are invoked as part of a deployment, so the permissions should be applied automatically every time you update your API.

In your case, you would use something like this:

.ebextensions/01-make-temp-folder-writeable.config

```<code>container_commands:
  chown_folder:
    command: "chown webapp temp_image"
  chmod_folder:
    command: "chmod 775 temp_image"
</code>```

Make sure you pay attention to your indentation - YAML files are very sensitive to whitespace.

Body:
ElasticBeanstalk deployments are considered immutable post-deployment, so you will probably have to change permissions on your temp folder. Thankfully, doing so is pretty straightforward. The mechanism for performing operations such as chmod or chown is through configuration files, described here. ElasticBeanstalk configuration files are invoked as part of a deployment, so the permissions should be applied automatically every time you update your API.

In your case, you would use something like this:

.ebextensions/01-make-temp-folder-writeable.config

container_commands:
  chown_folder:
    command: "chown webapp temp_image"
  chmod_folder:
    command: "chmod 775 temp_image"

Make sure you pay attention to your indentation - YAML files are very sensitive to whitespace.


问:
Reverse linked list returning new linked list
I need to implement a function that reverses a linked list but i don't know how to return a newly formed linked list as a result.

```<code>typedef struct node_t* Node;

struct node_t {
    int n;
    Node next;
};

// create a new node with value n
Node nodeCreate(int n)
{
    Node node = malloc(sizeof(*node));
    if (node == NULL) return NULL;

    node->n = n;
    node->next = NULL;

    return node;
}

// reversing the linked list
Node reverseList(Node list)
{
    if (list == NULL) return NULL;

    Node current, prev, next;
    current = rev_head;
    prev = NULL;

    while( current != NULL)
    {
        next = current->next;
        current->next = prev;
        prev = current;
        current = next;
    }

    list = prev;
    return list;
}
</code>```

This is the code I have written so far.

How do I insert this reverse linked list into a different new linked list within the function reverseList it self?

答:
You are juggling around your nodes on the original list, and modifying then in place - which means you have only one list, and modify its nodes.

If that is what you want, your code might work (as soon as you fix things like the rev_head variable that appears from nowhere) - and the new head of the list, which is on your prev variable: which means your code should just work.

(It is important that the typedef don't hide the pointer though, I'd suggest changing that.)

What you seem not to have understood quite well is that for this kind o structure, any node works as the head of a list - there is no "list" type, just "node" types - and if you happen to pick any node in the middle of a list, that will just represent a partial list, starting from that node as well. So when you change your previous "last" node to point to its previous "antecessor" as its "next", that is it: that node is now the head.

(The exception to this "node == list" equality is while the reversing algorithm is running - at that point you have nodes that point in one direction and nodes that point in another, and the extra "next" and "prev" variables provide the needed information to fix things. If this was production code, this part of the code would have to be protected in a thread-lock)

Otherwise, if you want to produce a reversed copy of the list, you will have to copy the old nodes along the way, and just fix where they are pointing.

```<code>#include <stdlib.h>
#include <string.h>

typedef struct node_t Node;
struct node_t {
    int n;
    Node next;
};

// create a new node with value n
Node *nodeCreate(int n) {
    Node *node = malloc(sizeof(*node));
    if (node == NULL) return NULL;

    node->n = n;
    node->next = NULL;

    return node;
}

void nodeCopy(Node *node_dst, Node *node_src) {
    if (node_src == NULL || node_dst == NULL || abs(node_dst - node_src) < sizeof(Node)) {
        return
    }
    memcpy(node_dst, node_src, sizeof(Node));
}

// reversing the linked list
Node *reverseList(Node *list) {
    Node *new_list, *prev;
    if (list == NULL) return NULL;

    new_list = nodeCreate(0);
    nodeCopy(new_list, list);
    new_list->next=NULL;
    prev = new_list;
    while(list->next != NULL) {
        list = list->next;
        new_list = nodeCreate(0);
        nodeCopy(new_list, list);
        new_list->next=prev;
        prev = new_list;
    }
    return new_list;
}
</code>```

Body:
I need to implement a function that reverses a linked list but i don't know how to return a newly formed linked list as a result.

typedef struct node_t* Node;

struct node_t {
    int n;
    Node next;
};

// create a new node with value n
Node nodeCreate(int n)
{
    Node node = malloc(sizeof(*node));
    if (node == NULL) return NULL;

    node->n = n;
    node->next = NULL;

    return node;
}

// reversing the linked list
Node reverseList(Node list)
{
    if (list == NULL) return NULL;

    Node current, prev, next;
    current = rev_head;
    prev = NULL;

    while( current != NULL)
    {
        next = current->next;
        current->next = prev;
        prev = current;
        current = next;
    }

    list = prev;
    return list;
}

This is the code I have written so far.

How do I insert this reverse linked list into a different new linked list within the function reverseList it self?

Body:
You are juggling around your nodes on the original list, and modifying then in place - which means you have only one list, and modify its nodes.

If that is what you want, your code might work (as soon as you fix things like the rev_head variable that appears from nowhere) - and the new head of the list, which is on your prev variable: which means your code should just work.

(It is important that the typedef don't hide the pointer though, I'd suggest changing that.)

What you seem not to have understood quite well is that for this kind o structure, any node works as the head of a list - there is no "list" type, just "node" types - and if you happen to pick any node in the middle of a list, that will just represent a partial list, starting from that node as well. So when you change your previous "last" node to point to its previous "antecessor" as its "next", that is it: that node is now the head.

(The exception to this "node == list" equality is while the reversing algorithm is running - at that point you have nodes that point in one direction and nodes that point in another, and the extra "next" and "prev" variables provide the needed information to fix things. If this was production code, this part of the code would have to be protected in a thread-lock)

Otherwise, if you want to produce a reversed copy of the list, you will have to copy the old nodes along the way, and just fix where they are pointing.

#include <stdlib.h>
#include <string.h>

typedef struct node_t Node;
struct node_t {
    int n;
    Node next;
};

// create a new node with value n
Node *nodeCreate(int n) {
    Node *node = malloc(sizeof(*node));
    if (node == NULL) return NULL;

    node->n = n;
    node->next = NULL;

    return node;
}

void nodeCopy(Node *node_dst, Node *node_src) {
    if (node_src == NULL || node_dst == NULL || abs(node_dst - node_src) < sizeof(Node)) {
        return
    }
    memcpy(node_dst, node_src, sizeof(Node));
}

// reversing the linked list
Node *reverseList(Node *list) {
    Node *new_list, *prev;
    if (list == NULL) return NULL;

    new_list = nodeCreate(0);
    nodeCopy(new_list, list);
    new_list->next=NULL;
    prev = new_list;
    while(list->next != NULL) {
        list = list->next;
        new_list = nodeCreate(0);
        nodeCopy(new_list, list);
        new_list->next=prev;
        prev = new_list;
    }
    return new_list;
}


问:
How to get underly cxxRecordDecl from typedefDecl
I have a piece of code:

```<code>typedef struct S1{
 int a;
 int b;
} S, *PS;
</code>```

I can get following AST with clang-check:

| |-CXXRecordDecl 0x3dfde48  col:16 implicit struct S1
| |-FieldDecl 0x3dfdef8  col:9 a 'int'
| -FieldDecl 0x3dfdf58 <line:4:5, col:9> col:9 b 'int'
|-TypedefDecl 0x3dfe010 <line:1:1, line:5:3> col:3 S 'struct S1':'struct S1'
|-ElaboratedType 0x3dfdfc0 'struct S1' sugar
|   -RecordType 0x3dfddc0 'struct S1'
|-CXXRecord 0x3dfdd28 'S1'
-TypedefDecl 0x3dfe0f0 <line:1:1, line:5:7> col:7 PS 'struct S1 *'
-PointerType 0x3dfe0a0 'struct S1 *'
    -ElaboratedType 0x3dfdfc0 'struct S1' sugar
-RecordType 0x3dfddc0 'struct S1'
        `-CXXRecord 0x3dfdd28 'S1'

If I use typedefDecl(), I can match S and PS, but how can I get the underlying cxxRecordDecl() ?

答:
One approach is to qualify the typedefDecl with traversal matchers. The first hop is to the type of the typedef, the second hop is to the declaration of that type. This terminates in the cxxRecordDecl that you are looking for.

```<code>typedefDecl(
  hasType(
    hasDeclaration(
      cxxRecordDecl().bind("the_struct")
))).bind("the_typedef")
</code>```

This works, but it has (at least) two problems. First, it also matches things you likely don't want matched, and second, it fails to match the pointer typedef declaration in your code. To see the first problem, run that matcher in clang-query. Putting your fragment into test_input_struct_type.cpp:

```<code>$ clang-query test_input_struct_type.cpp --
clang-query> let m1 typedefDecl( hasType( hasDeclaration(cxxRecordDecl().bind("the_struct"))))
clang-query> m m1

Match #1:

Match #2:

test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:9: note: "the_struct" binds here
typedef struct S1{
        ^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
2 matches.
</code>```

Match #2 looks fine, but what was match #1? I suspect that matcher is hitting some of the typedef nodes that seem to be inserted by the compiler at the beginning of the AST for the translation unit.

One way to fix the first problem is to add some more specificity:

```<code>typedefDecl(
  hasType(
    elaboratedType(
      namesType(
        recordType(
          hasDeclaration(
            cxxRecordDecl().bind("the_struct")
))))).bind("the_typedef")
</code>```

Back in clang-query:

```<code>clang-query> let m2  typedefDecl(hasType(elaboratedType( namesType( recordType( hasDeclaration(cxxRecordDecl().bind("the_struct")))) ))).bind("the_typedef")
clang-query> m m2

Match #1:

test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:9: note: "the_struct" binds here
typedef struct S1{
        ^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
1 match.
</code>```

What about the second problem--finding the pointer typedef? That requires a slightly different matcher:

```<code>typedefDecl(
  hasType(
    pointerType(
      pointee(
        hasDeclaration(
          cxxRecordDecl().bind("pointee_struct")
))))).bind("the_typedef")
</code>```

The two matchers can then be combined using anyOf. Back in clang-query:

```<code>clang-query> let m2a hasType(elaboratedType( namesType( recordType( hasDeclaration(cxxRecordDecl().bind("the_struct"))))))
clang-query> let m3a hasType(pointerType( pointee( hasDeclaration(cxxRecordDecl().bind("pointee_struct")))))
clang-query> let m4 typedefDecl( anyOf(m2a,m3a)).bind("the_typedef")
clang-query> m m4

Match #1:

test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:9: note: "the_struct" binds here
typedef struct S1{
        ^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~

Match #2:

test_input_struct_type.cpp:1:9: note: "pointee_struct" binds here
typedef struct S1{
        ^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
2 matches.
</code>```

Body:
I have a piece of code:

typedef struct S1{
 int a;
 int b;
} S, *PS;

I can get following AST with clang-check:

| |-CXXRecordDecl 0x3dfde48  col:16 implicit struct S1
| |-FieldDecl 0x3dfdef8  col:9 a 'int'
| -FieldDecl 0x3dfdf58 <line:4:5, col:9> col:9 b 'int'
|-TypedefDecl 0x3dfe010 <line:1:1, line:5:3> col:3 S 'struct S1':'struct S1'
|-ElaboratedType 0x3dfdfc0 'struct S1' sugar
|   -RecordType 0x3dfddc0 'struct S1'
|-CXXRecord 0x3dfdd28 'S1'
-TypedefDecl 0x3dfe0f0 <line:1:1, line:5:7> col:7 PS 'struct S1 *'
-PointerType 0x3dfe0a0 'struct S1 *'
    -ElaboratedType 0x3dfdfc0 'struct S1' sugar
-RecordType 0x3dfddc0 'struct S1'
        `-CXXRecord 0x3dfdd28 'S1'

If I use typedefDecl(), I can match S and PS, but how can I get the underlying cxxRecordDecl() ?

Body:
One approach is to qualify the typedefDecl with traversal matchers. The first hop is to the type of the typedef, the second hop is to the declaration of that type. This terminates in the cxxRecordDecl that you are looking for.

typedefDecl(
  hasType(
    hasDeclaration(
      cxxRecordDecl().bind("the_struct")
))).bind("the_typedef")

This works, but it has (at least) two problems. First, it also matches things you likely don't want matched, and second, it fails to match the pointer typedef declaration in your code. To see the first problem, run that matcher in clang-query. Putting your fragment into test_input_struct_type.cpp:

$ clang-query test_input_struct_type.cpp --
clang-query> let m1 typedefDecl( hasType( hasDeclaration(cxxRecordDecl().bind("the_struct"))))
clang-query> m m1

Match #1:

Match #2:

test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:9: note: "the_struct" binds here
typedef struct S1{
        ^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
2 matches.

Match #2 looks fine, but what was match #1? I suspect that matcher is hitting some of the typedef nodes that seem to be inserted by the compiler at the beginning of the AST for the translation unit.

One way to fix the first problem is to add some more specificity:

typedefDecl(
  hasType(
    elaboratedType(
      namesType(
        recordType(
          hasDeclaration(
            cxxRecordDecl().bind("the_struct")
))))).bind("the_typedef")

Back in clang-query:

clang-query> let m2  typedefDecl(hasType(elaboratedType( namesType( recordType( hasDeclaration(cxxRecordDecl().bind("the_struct")))) ))).bind("the_typedef")
clang-query> m m2

Match #1:

test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:9: note: "the_struct" binds here
typedef struct S1{
        ^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
1 match.

What about the second problem--finding the pointer typedef? That requires a slightly different matcher:

typedefDecl(
  hasType(
    pointerType(
      pointee(
        hasDeclaration(
          cxxRecordDecl().bind("pointee_struct")
))))).bind("the_typedef")

The two matchers can then be combined using anyOf. Back in clang-query:

clang-query> let m2a hasType(elaboratedType( namesType( recordType( hasDeclaration(cxxRecordDecl().bind("the_struct"))))))
clang-query> let m3a hasType(pointerType( pointee( hasDeclaration(cxxRecordDecl().bind("pointee_struct")))))
clang-query> let m4 typedefDecl( anyOf(m2a,m3a)).bind("the_typedef")
clang-query> m m4

Match #1:

test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:9: note: "the_struct" binds here
typedef struct S1{
        ^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~

Match #2:

test_input_struct_type.cpp:1:9: note: "pointee_struct" binds here
typedef struct S1{
        ^~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "root" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
test_input_struct_type.cpp:1:1: note: "the_typedef" binds here
typedef struct S1{
^~~~~~~~~~~~~~~~~~
2 matches.


问:
How to programmatically open a website and click buttons
How to use VBScript to implement the following:

Open web browser

Load a URL in web browser after opening

List item

Click buttons in the loaded browser

Is this possible using VBScript. Any examples of code to help get me started would be beneficial. Also, my web browser is Chrome.

答:
There is a Selenium webdriver created that works with VB.NET, VBA, and VBScript. Download and install the exe.

There are also lots of example scripts that show loading different browser types or in your case Chrome. Once loaded you just need to program what elements to navigate and click after loading your specific URL.

There might be other ways to launch and run commands against the web browser using VBScript. This is just one way.

SeleniumBasic v2.0.9.0 created by Florent Breheret and open source via git hub.

A Selenium based browser automation framework for VB.Net, Visual Basic Applications and VBScript

Script Example:

```<code>Set driver = CreateObject("Selenium.ChromeDriver")
driver.Start
WScript.Echo "Click OK to quit"
driver.Quit
</code>```

Here is the official SELENIUM page: selenium main page

UPDATE:
Here is a second option that is based on the same concept , but implemented a little different. I am not sure it meets your needs , but thought I would include it as another example.
VBS WebDriver

Examples using the VBS WebDriver which is intended to provide a simple binding for Selenium 2. The bindings include the full functionality of Selenium 2 (WebDriver).

Body:
There is a Selenium webdriver created that works with VB.NET, VBA, and VBScript. Download and install the exe.

There are also lots of example scripts that show loading different browser types or in your case Chrome. Once loaded you just need to program what elements to navigate and click after loading your specific URL.

There might be other ways to launch and run commands against the web browser using VBScript. This is just one way.

SeleniumBasic v2.0.9.0 created by Florent Breheret and open source via git hub.

A Selenium based browser automation framework for VB.Net, Visual Basic Applications and VBScript

Script Example:

Set driver = CreateObject("Selenium.ChromeDriver")
driver.Start
WScript.Echo "Click OK to quit"
driver.Quit

Here is the official SELENIUM page: selenium main page

UPDATE:
Here is a second option that is based on the same concept , but implemented a little different. I am not sure it meets your needs , but thought I would include it as another example.
VBS WebDriver

Examples using the VBS WebDriver which is intended to provide a simple binding for Selenium 2. The bindings include the full functionality of Selenium 2 (WebDriver).


问:
Highcharts heatmap logarithmic colorAxis fails when 0
I'm trying to implement a heatmap in highcharts with a logarithmic colorAxis, however, I keep getting highcharts error #10 (can't plot zero or subzero values on a logarithmic axis).

As I'm trying to apply the logarithmic property to the color axis and not the actual axis themselves, I believe my problem is caused by some of my bins having a frequency of zero (A heatmap colors by the frequency in each bin).

How can I get around this? Can I create a default function so that when a frequency is zero it assigns that bin a default color? I can't find any solutions in the docs.

Currently, my colorAxis object looks like this

```<code>colorAxis: {
  type: 'logarithmic',
  minColor: '#EEEEFF',
  maxColor: '#000022',
  stops: [
    [0, '#EFEFFF'],
    [0.67, '#4444FF'],
    [1, '#000022']
  ]
}
</code>```

答:
Logarithm doesn't have any value in 0 so your solution seems pretty neat. You need to apply some offset to the values that equal 0 - there's no other way.

If you want to be more consistent you can apply the offset to all the values. Then apply formatters(tooltip, data labels, color axis' labels) so that the user sees the value without the offset.

Live demo: http://jsfiddle.net/kkulig/jdf5wrdL/

Body:
I'm trying to implement a heatmap in highcharts with a logarithmic colorAxis, however, I keep getting highcharts error #10 (can't plot zero or subzero values on a logarithmic axis).

As I'm trying to apply the logarithmic property to the color axis and not the actual axis themselves, I believe my problem is caused by some of my bins having a frequency of zero (A heatmap colors by the frequency in each bin).

How can I get around this? Can I create a default function so that when a frequency is zero it assigns that bin a default color? I can't find any solutions in the docs.

Currently, my colorAxis object looks like this

colorAxis: {
  type: 'logarithmic',
  minColor: '#EEEEFF',
  maxColor: '#000022',
  stops: [
    [0, '#EFEFFF'],
    [0.67, '#4444FF'],
    [1, '#000022']
  ]
}


问:
Why does rails 3 show "(/)" when I use the link_to img_tag helpers?
here's the code:

```<code>    <%= link_to tag("img", { :src => "/images/logo.png", :alt => "logo"}, false), {:controller => 'frontpage', :action => 'index'}, :class => "logo" %>
</code>```

the output:

'(/)'

the '(/)' --minus the quotes, come at the end of the image

答:
Are you sure you don't have that floating in your HTML somewhere?

Also, you're doing a lot more work than necessary:

```<code><%= link_to image_tag('logo.png'), frontpages_path, :class => 'logo' %>
</code>```

That'll automatically assign "Logo" as the alt text, and assuming you're using RESTful routes, that frontpages_path helper will already exist.

ContentLicense: CC BY-SA 2.5

Body:
here's the code:

    <%= link_to tag("img", { :src => "/images/logo.png", :alt => "logo"}, false), {:controller => 'frontpage', :action => 'index'}, :class => "logo" %>

the output:

'(/)'

the '(/)' --minus the quotes, come at the end of the image

Body:
Are you sure you don't have that floating in your HTML somewhere?

Also, you're doing a lot more work than necessary:

<%= link_to image_tag('logo.png'), frontpages_path, :class => 'logo' %>

That'll automatically assign "Logo" as the alt text, and assuming you're using RESTful routes, that frontpages_path helper will already exist.


问:
Freezing part of layers in Inception V3 in TensorFlow with Python 3
I want to freeze the layers except the first three layers in the Inception v3 model with TensorFlow in Python 3 also modify the weights of these three layers to be able to re-initialize and re-train only the three first layers of the network. If this can't be done within the inception model, is there any other network (in TensorFlow) with which this could be done?

答:
This can be done in any network. To freeze the lower layers during training, the simplest solution is to give the optimizer the list of variables to train, excluding the variables from the lower layers:

train_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,
                               scope="hidden[34]|outputs")
training_op = optimizer.minimize(loss, var_list=train_vars)
```

The first line gets the list of all trainable variables in hidden layers 3 and 4 and in the output layer. This leaves out the variables in the hidden layers 1 and 2. The snippet above assumes the layers have the variable scopes hidden1, ... hidden4 and outputs; Inception model uses a different naming: Conv2d_2a_*, Conv2d_2b_*, AvgPool_1a_*, ...

Body:
This can be done in any network. To freeze the lower layers during training, the simplest solution is to give the optimizer the list of variables to train, excluding the variables from the lower layers:

train_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,
                               scope="hidden[34]|outputs")
training_op = optimizer.minimize(loss, var_list=train_vars)

The first line gets the list of all trainable variables in hidden layers 3 and 4 and in the output layer. This leaves out the variables in the hidden layers 1 and 2. The snippet above assumes the layers have the variable scopes hidden1, ... hidden4 and outputs; Inception model uses a different naming: Conv2d_2a_*, Conv2d_2b_*, AvgPool_1a_*, ...


问:
Google Cloud Networking Issue
I have some services stood up on Google Container Engine and they are hooked up to external IPs.

When I try to query on of these external IPs from within one of my services I get an error like

```<code>dial tcp xx.xx.xx.xx:5429: getsockopt: connection refused
</code>```

Using the exact same service, but running on my local machine, it can connect fine to the same IP and port.

Is there some sort of port opening that I need to do in Google Networking dashboard or in my Kuberenetes pod configuration to allow my pod to connect to this host?

答:
It is a firewall issue. It is trying to set up a connection through 5429 port, which surely is being blocked in the firewall rules.

You can find the Firewall console in the dashboard > Networking > VPC network > Firewall rules.

You only need to allow the connection in the needed port in the network where your instance is and it will work properly.

Title: Google Cloud Networking Issue

Body:
I have some services stood up on Google Container Engine and they are hooked up to external IPs.

When I try to query on of these external IPs from within one of my services I get an error like

dial tcp xx.xx.xx.xx:5429: getsockopt: connection refused

Using the exact same service, but running on my local machine, it can connect fine to the same IP and port.

Is there some sort of port opening that I need to do in Google Networking dashboard or in my Kuberenetes pod configuration to allow my pod to connect to this host?


问:
How to use string as a delimiter in getline() function in c++
I have structure member which takes the value of delimiter from XML.And I want use that structure member as delimiter . But as getline() function take delimiter as char only so my I'm stuck over there.

istream& getline (istream& is, string& str, char delim)

I have done following thing in my code:-

```<code>string ABC = struct.delimiter;    // Here struct.delimiter is takes value of
                                     d delimiter from XML delimiter = '='
</code>```

and I want use as

```<code>getline(string1,string2, ABC);
</code>```

Is it possible?
or
Is there another way to do it?

答:
You cannot achieve this with a getLine, the best way I know of to do this would be to get your line, store it in a string and use the find() function to find your delimiters.

```<code>string string; // Your line
string ABC = struct.delimiter; // Delimited
getline(input, string); // Get line from stream - Thx Kevin
string subStr = str.substr(0, str.find(ABC)); // this will get you the first segment
</code>```

From here on you can develop your loop to go over the read data and find all segments.

Body:
I have structure member which takes the value of delimiter from XML.And I want use that structure member as delimiter . But as getline() function take delimiter as char only so my I'm stuck over there.

istream& getline (istream& is, string& str, char delim)

I have done following thing in my code:-

string ABC = struct.delimiter;    // Here struct.delimiter is takes value of
                                     d delimiter from XML delimiter = '='

and I want use as

getline(string1,string2, ABC);

Is it possible?
or
Is there another way to do it?

Body:
You cannot achieve this with a getLine, the best way I know of to do this would be to get your line, store it in a string and use the find() function to find your delimiters.

string string; // Your line
string ABC = struct.delimiter; // Delimited
getline(input, string); // Get line from stream - Thx Kevin
string subStr = str.substr(0, str.find(ABC)); // this will get you the first segment

From here on you can develop your loop to go over the read data and find all segments.