Android ListView鼠标模式下ListView回滚问题

news2024/11/16 17:52:00

在这里插入图片描述

概述

     在 Android 应用程序中,ListView 是一种常用的控件,用于显示可滚动列表数据。然而,当在鼠标操作模式下使用 ListView 时,可能会遇到一个问题:点击列表项时,列表会回滚到指定位置,这可能会导致用户体验不佳。
在这里插入图片描述

分析

     通过测试发现, 回滚的位置与列表的选中项位置有关系.
在启动activity后, 不执行其他操作时, 通过滚轮直接滚动到列表最下方, 再点击按键, 调用了adapter.notifyDataSetChanged 列表回滚;

dumpsys
dumpsys activity com.android.tester/.cases.ListViewBackground

出现回滚时

View Hierarchy:
      DecorView@4ef06ab[ListViewBackground]
        com.android.internal.widget.ActionBarOverlayLayout{1102108 V.E...... ........ 0,0-1920,1080 #1020230 android:id/decor_content_parent}
          android.widget.FrameLayout{21eb0a1 V.E...... ........ 0,96-1920,1080 #1020002 android:id/content}
            android.widget.LinearLayout{e6872c6 V.E...... ........ 0,0-1920,984}
              android.widget.ListView{956287 VFED.VC.. .F...... 0,0-1920,984 #7f030002 app:id/lvRight}
                android.widget.LinearLayout{f0a45b4 V.E...... ..S..... 0,0-1920,173}
                  android.widget.TextView{5d4b5dd V.ED..... ..S..... 0,0-1735,173 #7f030004 app:id/tv}
                  android.widget.Button{e8f552 VFED..C.. ..S..... 1735,0-1920,173 #7f030000 app:id/btn}
                android.widget.LinearLayout{37d149e V.E...... ........ 0,175-1920,348}
                  android.widget.TextView{8be1b7f V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
                  android.widget.Button{88c974c VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
                android.widget.LinearLayout{d5ba023 V.E...... ........ 0,350-1920,523}
                  android.widget.TextView{8e00920 V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
                  android.widget.Button{8ebd2d9 VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
                android.widget.LinearLayout{abdc395 V.E...... ........ 0,525-1920,698}
                  android.widget.TextView{ea1dcaa V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
                  android.widget.Button{1a2f09b VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
                android.widget.LinearLayout{a91dc38 V.E...... ........ 0,700-1920,873}
                  android.widget.TextView{c840411 V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
                  android.widget.Button{3991976 VFED..C.. ....H... 1735,0-1920,173 #7f030000 app:id/btn}
                android.widget.LinearLayout{535fb77 V.E...... ........ 0,875-1920,1048}
                  android.widget.TextView{fa483e4 V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
                  android.widget.Button{f93d04d VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
          com.android.internal.widget.ActionBarContainer{3f55702 V.ED..... ........ 0,0-1920,96 #102018e android:id/action_bar_container}
            android.widget.Toolbar{d84d813 V.E...... ........ 0,0-1920,96 #102018d android:id/action_bar}
              android.widget.TextView{d17fa50 V.ED..... ........ 36,27-122,68}
            com.android.internal.widget.ActionBarContextView{b5a2449 G.E...... ......I. 0,0-0,0 #1020192 android:id/action_context_bar}

在启动activity后, 点击列表项(不是BTN所在区域), 通过滚轮直接滚动到列表最下方, 再点击按键, 调用了adapter.notifyDataSetChanged 列表不回滚;

不会滚

View Hierarchy:
      DecorView@4ef06ab[ListViewBackground]
        com.android.internal.widget.ActionBarOverlayLayout{1102108 V.E...... ........ 0,0-1920,1080 #1020230 android:id/decor_content_parent}
          android.widget.FrameLayout{21eb0a1 V.E...... ........ 0,96-1920,1080 #1020002 android:id/content}
            android.widget.LinearLayout{e6872c6 V.E...... ........ 0,0-1920,984}
              android.widget.ListView{956287 VFED.VC.. .F..H... 0,0-1920,984 #7f030002 app:id/lvRight}
                android.widget.LinearLayout{f0a45b4 V.E...... ........ 0,0-1920,173}
                  android.widget.TextView{5d4b5dd V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
                  android.widget.Button{e8f552 VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
                android.widget.LinearLayout{d5ba023 V.E...... ........ 0,175-1920,348}
                  android.widget.TextView{8e00920 V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
                  android.widget.Button{8ebd2d9 VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
                android.widget.LinearLayout{37d149e V.E...... ........ 0,350-1920,523}
                  android.widget.TextView{8be1b7f V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
                  android.widget.Button{88c974c VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
                android.widget.LinearLayout{abdc395 V.E...... ........ 0,525-1920,698}
                  android.widget.TextView{ea1dcaa V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
                  android.widget.Button{1a2f09b VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
                android.widget.LinearLayout{a91dc38 V.E...... ........ 0,700-1920,873}
                  android.widget.TextView{c840411 V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
                  android.widget.Button{3991976 VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
                android.widget.LinearLayout{535fb77 V.E...... ........ 0,875-1920,1048}
                  android.widget.TextView{fa483e4 V.ED..... ........ 0,0-1735,173 #7f030004 app:id/tv}
                  android.widget.Button{f93d04d VFED..C.. ........ 1735,0-1920,173 #7f030000 app:id/btn}
          com.android.internal.widget.ActionBarContainer{3f55702 V.ED..... ........ 0,0-1920,96 #102018e android:id/action_bar_container}
            android.widget.Toolbar{d84d813 V.E...... ........ 0,0-1920,96 #102018d android:id/action_bar}
              android.widget.TextView{d17fa50 V.ED..... ........ 36,27-122,68}
            com.android.internal.widget.ActionBarContextView{b5a2449 G.E...... ......I. 0,0-0,0 #1020192 android:id/action_context_bar}

View状态输出的源码:

frameworks/base/core/java/android/view/View.java


   public String toString() {
        StringBuilder out = new StringBuilder(128);
        out.append(getClass().getName());
        out.append('{');
        out.append(Integer.toHexString(System.identityHashCode(this)));
        out.append(' ');
        switch (mViewFlags&VISIBILITY_MASK) {
            case VISIBLE: out.append('V'); break;
            case INVISIBLE: out.append('I'); break;
            case GONE: out.append('G'); break;
            default: out.append('.'); break;
        }
        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
        out.append(' ');
        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
            out.append('p');
        } else {
            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
        }
        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
        out.append(' ');
        out.append(mLeft);
        out.append(',');
        out.append(mTop);
        out.append('-');
        out.append(mRight);
        out.append(',');
        out.append(mBottom);
      }

从上面的代码可以看出, S代表了View的Selected状态. 通过操作按键的 键改变列表的选中项, 可以看出列表的S项跟随选中项. 而回滚的位置就是选中的位置, 回滚的效果与 setSelection(int pos)相同;

代码中打印ListView.getSelectedItemPosition的返回值, 默认是 0(回滚), 当点击列表项后变为 -1(不回滚)

默认选中从何而来?

打印出setSelected的堆栈信息:

 java.lang.Exception: setSelected
   at com.android.tester.widgets.XTV.setSelected(XTV.java:23)
   at android.view.ViewGroup.dispatchSetSelected(ViewGroup.java:4426)
   at android.view.View.setSelected(View.java:22276)
   at android.widget.ListView.setupChild(ListView.java:2102)
   at android.widget.ListView.makeAndAddView(ListView.java:2055)
   at android.widget.ListView.fillDown(ListView.java:786)
   at android.widget.ListView.fillFromTop(ListView.java:847)
   at android.widget.ListView.layoutChildren(ListView.java:1826)
   at android.widget.AbsListView.onLayout(AbsListView.java:2165)
   at android.view.View.layout(View.java:20672)
   at android.view.ViewGroup.layout(ViewGroup.java:6194)
   at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
   at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1801)
   at android.widget.LinearLayout.onLayout(LinearLayout.java:1567)
   at android.view.View.layout(View.java:20672)
   at android.view.ViewGroup.layout(ViewGroup.java:6194)
   at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
   at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
   at android.view.View.layout(View.java:20672)
   at android.view.ViewGroup.layout(ViewGroup.java:6194)
   at com.android.internal.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:508)
   at android.view.View.layout(View.java:20672)
   at android.view.ViewGroup.layout(ViewGroup.java:6194)
   at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
   at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
   at com.android.internal.policy.DecorView.onLayout(DecorView.java:753)
   at android.view.View.layout(View.java:20672)
   at android.view.ViewGroup.layout(ViewGroup.java:6194)
   at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2796)
   at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2323)
   at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1462)
   at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7187)
   at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
   at android.view.Choreographer.doCallbacks(Choreographer.java:761)
   at android.view.Choreographer.doFrame(Choreographer.java:696)
   at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
   at android.os.Handler.handleCallback(Handler.java:873)
   at android.os.Handler.dispatchMessage(Handler.java:99)
   at android.os.Looper.loop(Looper.java:193)
   at android.app.ActivityThread.main(ActivityThread.java:6669)
   at java.lang.reflect.Method.invoke(Native Method)
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:951)


源码中:

frameworks/base/core/java/android/widget/ListView.java

    /**
     * Fills the list from pos down to the end of the list view.
     *
     * @param pos The first position to put in the list
     *
     * @param nextTop The location where the top of the item associated with pos
     *        should be drawn
     *
     * @return The view that is currently selected, if it happens to be in the
     *         range that we draw.
     */
    private View fillDown(int pos, int nextTop) {
        View selectedView = null;

        int end = (mBottom - mTop);
        if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
            end -= mListPadding.bottom;
        }

        while (nextTop < end && pos < mItemCount) {
            // is this the selected item?
            boolean selected = pos == mSelectedPosition;
            View child = makeAndAddView(pos, nextTop, true, mListPadding.left, selected);

            nextTop = child.getBottom() + mDividerHeight;
            if (selected) {
                selectedView = child;
            }
            pos++;
        }

        setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1);
        return selectedView;
    }

重点看下: mSelectedPosition

    /**
     * Find a position that can be selected (i.e., is not a separator).
     *
     * @param position The starting position to look at.
     * @param lookDown Whether to look down for other positions.
     * @return The next selectable position starting at position and then searching either up or
     *         down. Returns {@link #INVALID_POSITION} if nothing can be found.
     */
    @Override
    int lookForSelectablePosition(int position, boolean lookDown) {
        final ListAdapter adapter = mAdapter;
        if (adapter == null || isInTouchMode()) {
            return INVALID_POSITION;
        }

        final int count = adapter.getCount();
        if (!mAreAllItemsSelectable) {
            if (lookDown) {
                position = Math.max(0, position);
                while (position < count && !adapter.isEnabled(position)) {
                    position++;
                }
            } else {
                position = Math.min(position, count - 1);
                while (position >= 0 && !adapter.isEnabled(position)) {
                    position--;
                }
            }
        }

        if (position < 0 || position >= count) {
            return INVALID_POSITION;
        }

        return position;
    }

鼠标的操作模式中, isInTouchMode 返回的是false, mSelectedPosition = 0;
当点击了列表项后, isInTouchMode 则返回了true, mSelectedPosition = INVALID_POSITION (-1)

解决回滚

一个取巧的办法: 在鼠标输入的模式下, 会导致View判断isInTouchMode返回false, 那么, 重写该判断方法即可.

package com.android.tester.widgets;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;

public class XLV extends ListView {
    public XLV(Context context) {
        super(context);
    }

    public XLV(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public XLV(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean isInTouchMode() {
        return true;
    }
}

 


 

设置列表项的背景: android:listSelector 和 android:background 的效果并不相同!

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape>
            <solid android:color="@color/red"/>
        </shape>
    </item>
    <item android:state_focused="true">
        <shape>
            <solid android:color="@color/yellow"/>
        </shape>
    </item>
    <item android:state_checked="true">
        <shape>
            <solid android:color="@color/cyan"/>
        </shape>
    </item>
    <item android:state_selected="true">
        <shape>
            <solid android:color="@color/blue"/>
        </shape>
    </item>
    <item android:state_activated="true">
        <shape>
            <solid android:color="@color/purple"/>
        </shape>
    </item>
    <item>
        <shape>
            <solid android:color="@color/trans"/>
        </shape>
    </item>
</selector>

设置列表项的方法有两种, 实际效果却不相同:

android:listSelector 有自己的想法, 测试的代码中, 似乎它对 state_focused (黄色)相当执着, 即使列表项在View的状态已经是Selected, 它依然不变初衷.

从dumpsys可以看到:

    android.widget.LinearLayout{9af619f V.E...... ..S..... 0,0-1920,173}
                  com.android.tester.widgets.XTV{f6532ec V.ED..... ..S..... 0,0-1735,173 #7f030004 app:id/tv}
                  android.widget.Button{222c6b5 VFED..C.. ..S..... 1735,0-1920,173 #7f030000 app:id/btn}

显示效果:
在这里插入图片描述
 
 

为列表项单独设置android:background会更灵活一点

  //会残留黄色背景
  android:listSelector="@null"
  //背景干净.
  android:listSelector="@color/trans"

修改列表项背景:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:descendantFocusability="blocksDescendants"
    android:background="@drawable/selector_item_bg"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.android.tester.widgets.XTV android:id="@+id/tv"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:textColor="#FF987654"
        android:gravity="center_vertical"
        android:layout_height="match_parent"/>
    <Button android:id="@+id/btn"
        android:text="BTN"
        android:padding="48dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</LinearLayout>

参考代码

layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!--<TextView android:id="@+id/tvLeft"
        android:background="@drawable/selector_border_bg"
        android:layout_width="0dp"
        android:layout_weight="0.3"
        android:layout_height="wrap_content"/>-->

    <com.android.tester.widgets.XLV
        android:id="@+id/lvRight"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:drawSelectorOnTop="false"
        android:cacheColorHint="@color/trans"
        android:listSelector="@null"
        />
</LinearLayout>

layout item

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:descendantFocusability="blocksDescendants"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.android.tester.widgets.XTV android:id="@+id/tv"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:textColor="#FF987654"
        android:gravity="center_vertical"
        android:layout_height="match_parent"/>
    <Button android:id="@+id/btn"
        android:text="BTN"
        android:padding="48dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</LinearLayout>

Activity

package com.android.tester.cases;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;

import com.android.tester.R;

import java.util.ArrayList;

public class ListViewBackground extends Activity {
    final String TAG = "ListViewBackground";
    //TextView tvLeft;
    ListView lvRight;
    LVAdapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.listview_background);
        /*tvLeft = (TextView) findViewById(R.id.tvLeft);
        tvLeft.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                lvRight.setSelection(0);
            }
        });*/
        lvRight = (ListView)findViewById(R.id.lvRight);
        lvRight.setChoiceMode(AbsListView.CHOICE_MODE_NONE);
        adapter = new LVAdapter();
        for(int i = 0; i < 50; i ++){
            adapter.addData("ITEM " + i);
        }
        lvRight.setAdapter(adapter);
        lvRight.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                /*tvLeft.setText(adapter.content.get(position));
                tvLeft.setSelected(position%3 == 0);
                tvLeft.setPressed(position%2 == 0);*/
                //lvRight.setSelection(position);
            }
        });
    }

    class LVAdapter extends BaseAdapter{
        ArrayList<Data> content = new ArrayList<>();
        void addData(String str){
            int pos = content.size();
            content.add(new Data());
            content.get(pos).content = str;
            content.get(pos).pos = pos;

        }
        @Override
        public int getCount() {
            return content.size();
        }

        @Override
        public Object getItem(int position) {
            return content.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TAG tag = null;
            if(convertView != null && convertView.getTag() != null){
                tag = (TAG)convertView.getTag();
            }else{
                tag = new TAG();
                convertView = getLayoutInflater().inflate(R.layout.layout_item_lv_background, null, false);
                tag.tv = convertView.findViewById(R.id.tv);
                tag.btn = convertView.findViewById(R.id.btn);
                tag.btn.setOnClickListener(btnClick);
                convertView.setTag(tag);
            }
            tag.tv.setText(content.get(position).content);
            tag.btn.setTag(position);
            //convertView.setSelected(content.get(position).selected);
            return convertView;
        }

        View.OnClickListener btnClick = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int pos = (int)v.getTag();
                //tvLeft.setText("Click Button " + pos);
                Log.d(TAG, "onClick isItemChecked=" + lvRight.isItemChecked(pos));
                Log.d(TAG, "onClick selected item pos=" + lvRight.getSelectedItemPosition());
                //lvRight.setSelection(pos);
                //lvRight.setItemChecked(pos, true);
                //content.get(pos).selected = true;
                notifyDataSetChanged();
            }
        };

        class TAG{
            TextView tv;
            Button btn;
        }

        class Data{
            int pos;
            boolean selected;
            String content;
        }
    }
}

XLV.java

package com.android.tester.widgets;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;

public class XLV extends ListView {
    public XLV(Context context) {
        super(context);
    }

    public XLV(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public XLV(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean isInTouchMode() {
        return true;
    }
}

参考

ListView的多选单选模式
listview的属性listselector使用解析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1697969.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows、Linux下,基于QT的打包方法

整理这篇文档的意义在于&#xff1a;自己走了很多弯路&#xff0c;淋过雨所以想为别人撑伞&#xff0c;也方便回顾&#xff0c;仅供参考 ps: 第一次做Windows下打包&#xff0c;用了2小时&#xff0c;第二次20秒第一次做Linux(ubuntu)下打包&#xff0c;用了8小时&#xff0c;…

linux笔记6--shell相关

文章目录 1. 查看当前的shell类型2. ps -f命令3. 父子shell4. 分号在命令里的作用问题&#xff1a;环境变量echo&#xff1a; 5. sleep和jobssleep:jobs:例子&#xff1a;&: 6. 外部命令和内建命令图解外部命令type命令 7. history命令8. alias命令9. 推荐 1. 查看当前的sh…

C/C++ vector详解

要想了解STL&#xff0c;就必须会看&#xff1a; cplusplus.comhttps://legacy.cplusplus.com/ 官方内容全都是英文的&#xff0c;可以参考&#xff1a; C/C初始识https://blog.csdn.net/2301_77087344/article/details/138596294?spm1001.2014.3001.5501 vector&#xff…

01JAVA基础

目录 1.基础语法 1.1 注释 1.2 关键字 1.3 常量 1.4 数据类型 1.5 变量 1.6 标识符 1.7 类型转换 2.算数运算符和分支语句 2.1 算数运算符 1.常规运算符 2.赋值运算符 3.自增自减 4.关系运算符 5.逻辑运算符 6.三元运算符 2.2 数据输入(Scanner) 2.3 分支判断…

抖店如何打造出爆品?学好这几招,轻松打爆新品流量

大家好&#xff0c;我是电商花花。 近年来&#xff0c;抖店商家越来越多&#xff0c;而选品&#xff0c;爆品就是我们商家竞争的核心了&#xff0c;谁能选出好的新品&#xff0c;打造出爆品&#xff0c;谁的会赚的多&#xff0c;销量多。 做抖音小店想出单&#xff0c;想赚钱…

老外卖27刀每月的教程已经更新

用了两天半的时间&#xff0c;边学习&#xff0c;边整理了一份老外的视频教程&#xff0c;涉及Facebook&#xff0c;YouTube&#xff0c;tiktok等大的流量平台&#xff0c;有案例&#xff0c;有分析&#xff0c;有如何做。 这个教程是老外讲的&#xff0c;没有什么玄乎的塑造价…

UneMeta与日本顶级IP熊本熊合作,首个NFT玩法揭秘

UneMeta 生态是一个备受加密市场以及动漫 IP 市场关注的老牌 Web3 数字资产平台&#xff0c;旨在架起现实艺术 IP 和 NFT 艺术社区之间的桥梁&#xff0c;以促进 Web3 社区的包容性和多样性。并期望基于生态一流的产品体验和平台属性&#xff0c;打造一个包容交汇的元宇宙社区。…

美发店服务预约会员小程序的作用是什么

美发店不同于美容美甲&#xff0c;男女都是必需且年龄层几乎不限&#xff0c;商家在市场拓展时只要方法得当相对比较容易&#xff0c;当今客户适应于线上信息获取、咨询及实际内容开展&#xff0c;商家也需要赋能和提升自身服务效率&#xff0c;合理化管理。 运用【雨科】平台…

经济寒冬下的黄金跳板:方案、活动、竞标一手掌握

推荐策划人必备的宝藏地产策划资源平台&#xff0c; 订阅浩叫&#xff1a;地产营销策划圈。这个平台简直是地产策划人的百宝箱&#xff0c;里面藏着无数的策划秘籍&#xff0c;等着你来挖掘。 这个平台就像是一个大型的方案库&#xff0c;里面收录了众多知名地产企业的内部资料…

用three.js+echarts给公司写了一个站点数据大屏系统经验总结

时间过的好快,参加公司的新项目研发快一年了,五一机器人项目首秀,我们遇到了高并发集中下单情景,然后海量数据处理场景来了,给我在后端领域的高并发实践业务上画上了漂亮的一笔经验。人都是在磨练中成长,我很感谢这次给我的机会,虽然有点累,但也有点小成就。正好现在有…

docker 上面安装 Nginx 以及设置访问 IP 就可以访问前端工程

docker 运行 Nginx 第一步&#xff1a;搜索下镜像 首先可以使用 docker search nginx 搜索 nginx 服务 docker search nginx相关控制台输出&#xff1a; NAME DESCRIPTION STARS OFFICIAL…

电子商务网站(网上商店PetShop)

PetShop是一个范例&#xff0c;微软用它来展示.Net企业系统开发的能力。PetShop随着版本的不断更新&#xff0c;至现在基于.Net2.0的PetShop 4.0为止&#xff0c;整个设计逐渐变得成熟而优雅&#xff0c;有很多可以借鉴之处。PetShop是一个小型的项目&#xff0c;系统架构与代码…

统计信号处理基础 习题解答10-2

题目 两个随机变量x和y&#xff0c;如果联合PDF分解为&#xff1a; 那么称他们为条件独立的。在上式中z是条件随机变量。 我们观察 其中, , 是相互独立的。证明和是条件独立的。给出条件变量是A。和是无条件独立么&#xff1f;也就是 成立么&#xff1f;为了回答这个问题&…

flutter项目运行报错Exception: Gradle task assembleDebug failed with exit code 1各种报错合集

1.报错 Launching lib/main.dart on sdk gphone64 arm64 in debug mode... Running Gradle task assembleDebug... Exception in thread "main" java.net.ConnectException: Operation timed out at java.base/sun.nio.ch.Net.connect0(Native Method) at j…

【模版方法设计模式】

文章目录 模板方法设计模式模板方法的设计原则模板方法设计模式组成部分代码实现抽象类实现具体实现类执行 模板方法设计模式 模版方法设计模式&#xff08;Template Method Pattern&#xff09;是一种行为设计模式&#xff0c;它定义了一个操作中的算法骨架&#xff0c;而将一…

欢乐钓鱼大师游戏攻略:自动钓鱼技巧!

《欢乐钓鱼大师》是一款极具趣味性和挑战性的钓鱼模拟游戏&#xff0c;为玩家提供了一个体验钓鱼乐趣的虚拟世界。从湖泊到河流&#xff0c;再到广袤的海洋&#xff0c;游戏中的各种钓场让人流连忘返。无论是新手钓友&#xff0c;还是经验丰富的老钓手&#xff0c;都可以在游戏…

VMware虚拟机安装Windows server 2022超详细教程

文章目录 ISO下载安装步骤总结 ISO下载 链接&#xff1a;https://pan.baidu.com/s/19Z2q9KFKZq0pLisPZLn7_g 提取码&#xff1a;3pgn 安装步骤 安装完打开虚拟机后发现引导程序无法正常执行 解决方法见我的上一篇文章&#xff1a;http://t.csdnimg.cn/PzfOz 问题解决完后正常…

Dbs封装_连接池

1.Dbs封装 每一个数据库都对应着一个dao 每个dao势必存在公共部分 我们需要将公共部分抽取出来 封装成一个工具类 保留个性化代码即可 我们的工具类一般命名为xxxs 比如Strings 就是字符串相关的工具类 而工具类 我们将其放置于util包中我们以是否有<T>区分泛型方法和非泛…

如何恢复未保存或丢失的Word文档?

许多用户会遇到Word文档未保存而关闭的问题。实际上&#xff0c;您不会立即丢失未保存的文档数据。请不要对文档进行进一步的更改&#xff0c;例如修改并再次保存。您仍然有机会恢复未保存的Word文档。有一些方法可以帮助您恢复未保存的 Word 文档。 如果您不幸遇到这样的问题…