Android打造一个高性能无限层级显示的树形控件(Android树形控件)

Android使用ListView实现一个高性能无限层级显示的树形控件:

最近公司的Android项目里有一个地方需要选择某公司的所有部门,因为手机屏幕有限所以并不能像网页那样显示树状结构,但是如果只是用列表依次显示所有的部门又会让用户很难找到想要找的部门(即使加上搜索功能也很难表现出层级关系),由于系统控件ExpandableListView 只能显示两级,加上数据集的组织比较麻烦,所以就使用ListView来实现如下的树形展示效果。至于为什么使用listview最大的好处就是它自带控件复用功能,我们不用去处理这个复杂的问题。最终效果如下:

Center

分析:

因为要展示的是一个树形结构,所以每一条记录必须拥有一个指向父亲节点的字段。为了体现出层级结构,其实就是增加缩进就可以了。当然说起来很简单,但是做起来的时候会有很多地方值得注意,比如说如何处理展开和收缩,以及跨级展开,收缩,如何得到当前是第几层从而处理缩进等等,再比如说如果数据量比较大的话性能怎么样等等一系列问题。

接下来我们就以层级显示一个公司的所有部门为需求来实现一下,其实只要具有树形结构我们都可以这样做。

实现思路以及使用方法:

首先我们要定义一个抽象类,其中包含必需的字段和方法:

 
  1. /**
  2. * Created by HQOCSHheqing on 2016/8/2.
  3. *
  4. * @description 节点抽象类(泛型T主要是考虑到ID和parentID有可能是int型也有可能是String型
  5. * 即这里可以传入Integer或者String,具体什么类型由子类指定
  6. ,因为这两种类型比较是否相等的方式不同:一个是用 “==”,一个是用 equals() 函数)
  7. */
  8. public abstract class Node<T> {
  9. private int _level = -1;//当前节点的层级,初始值-1 后面会讲到
  10. private List<Node> _childrenList = new ArrayList<>();//所有的孩子节点
  11. private Node _parent;//父亲节点
  12. private int _icon;//图标资源ID
  13. private boolean isExpand = false;//当前状态是否展开
  14. public abstract T get_id();//得到当前节点ID
  15. public abstract T get_parentId();//得到当前节点的父ID
  16. public abstract String get_label();//要显示的内容
  17. public abstract boolean parent(Node dest);//判断当前节点是否是dest的父亲节点
  18. public abstract boolean child(Node dest);//判断当前节点是否是dest的孩子节点
  19. public int get_level() {
  20. if (_level == -1){//如果是 -1 的话就递归获取
  21. //因为是树形结构,所以此处想要得到当前节点的层级
  22. //,必须递归调用,但是递归效率低下,如果每次都递归获取会严重影响性能,所以我们把第一次
  23. //得到的结果保存起来避免每次递归获取
  24. int level = _parent == null ? 1 : _parent.get_level()+1;
  25. _level = level;
  26. return _level;
  27. }
  28. return _level;
  29. }
  30. public void set_level(int _level) {
  31. this._level = _level;
  32. }
  33. public List<Node> get_childrenList() {
  34. return _childrenList;
  35. }
  36. public void set_childrenList(List<Node> _childrenList) {
  37. this._childrenList = _childrenList;
  38. }
  39. public Node get_parent() {
  40. return _parent;
  41. }
  42. public void set_parent(Node _parent) {
  43. this._parent = _parent;
  44. }
  45. public int get_icon() {
  46. return _icon;
  47. }
  48. public void set_icon(int _icon) {
  49. this._icon = _icon;
  50. }
  51. public boolean isExpand() {
  52. return isExpand;
  53. }
  54. public void setIsExpand(boolean isExpand) {
  55. this.isExpand = isExpand;
  56. if (isExpand){
  57. _icon = R.mipmap.collapse;
  58. }else{
  59. _icon = R.mipmap.expand;
  60. }
  61. }
  62. public boolean isRoot(){
  63. return _parent == null;
  64. }
  65. public boolean isLeaf(){
  66. return _childrenList.size() <= 0;
  67. }
  68. }

将我们要树状显示的实体继承此抽象类,我们一部门ID以及parentid为integer型为例:

 
  1. /**
  2. * Created by HQOCSHheqing on 2016/8/2.
  3. *
  4. * @description 部门类(继承Node),此处的泛型Integer是因为ID和parentID都为int
  5. * ,如果为String传入泛型String即可,如果传入String,记得修改<span style="font-family: Arial, Helvetica, sans-serif;">parent和child方法,因为比较相等的方式不同。</span>
  6. */
  7. public class Dept extends Node<Integer>{
  8. private int id;//部门ID
  9. private int parentId;//父亲节点ID
  10. private String name;//部门名称
  11. public Dept() {
  12. }
  13. public Dept(int id, int parentId, String name) {
  14. this.id = id;
  15. this.parentId = parentId;
  16. this.name = name;
  17. }
  18. /**
  19. * 此处返回节点ID
  20. * @return
  21. */
  22. @Override
  23. public Integer get_id() {
  24. return id;
  25. }
  26. /**
  27. * 此处返回父亲节点ID
  28. * @return
  29. */
  30. @Override
  31. public Integer get_parentId() {
  32. return parentId;
  33. }
  34. @Override
  35. public String get_label() {
  36. return name;
  37. }
  38. @Override
  39. public boolean parent(Node dest) {
  40. if (id == ((Integer)dest.get_parentId()).intValue()){
  41. return true;
  42. }
  43. return false;
  44. }
  45. @Override
  46. public boolean child(Node dest) {
  47. if (parentId == ((Integer)dest.get_id()).intValue()){
  48. return true;
  49. }
  50. return false;
  51. }
  52. public int getId() {
  53. return id;
  54. }
  55. public void setId(int id) {
  56. this.id = id;
  57. }
  58. public int getParentId() {
  59. return parentId;
  60. }
  61. public void setParentId(int parentId) {
  62. this.parentId = parentId;
  63. }
  64. public String getName() {
  65. return name;
  66. }
  67. public void setName(String name) {
  68. this.name = name;
  69. }
  70. }

写一个帮助类:主要是整理节点与节点之间的关系,构造森林(有可能构造出多个树)。

 
  1. /**
  2. * Created by HQOCSHheqing on 2016/8/2.
  3. *
  4. * @description 节点帮助类
  5. */
  6. public class NodeHelper {
  7. /**
  8. * 传入所有的要展示的节点数据
  9. * @param nodeList 返回值是所有的根节点
  10. * @return
  11. */
  12. public static List<Node> sortNodes(List<Node> nodeList){
  13. List<Node> rootNodes = new ArrayList<>();
  14. int size = nodeList.size();
  15. Node m;
  16. Node n;
  17. //两个for循环整理出所有数据之间的斧子关系,最后会构造出一个森林(就是可能有多棵树)
  18. for (int i = 0;i < size;i++){
  19. m = nodeList.get(i);
  20. for (int j = i+1;j < size;j++){
  21. n = nodeList.get(j);
  22. if (m.parent(n)){
  23. m.get_childrenList().add(n);
  24. n.set_parent(m);
  25. }else if (m.child(n)){
  26. n.get_childrenList().add(m);
  27. m.set_parent(n);
  28. }
  29. }
  30. }
  31. //找出所有的树根,同事设置相应的图标(后面你会发现其实这里的主要
  32. // 作用是设置叶节点和非叶节点的图标)
  33. for (int i = 0;i < size;i++){
  34. m = nodeList.get(i);
  35. if (m.isRoot()){
  36. rootNodes.add(m);
  37. }
  38. setNodeIcon(m);
  39. }
  40. nodeList.clear();//此时所有的关系已经整理完成了
  41. // ,森林构造完成,可以清空之前的数据,释放内存,提高性能
  42. // ,如果之前的数据还有用的话就不清空
  43. nodeList = rootNodes;//返回所有的根节点
  44. rootNodes = null;
  45. return nodeList;
  46. }
  47. /**
  48. * 设置图标
  49. * @param node
  50. */
  51. private static void setNodeIcon(Node node){
  52. if (!node.isLeaf()){
  53. if (node.isExpand()){
  54. node.set_icon(R.mipmap.collapse);
  55. }else{
  56. node.set_icon(R.mipmap.expand);
  57. }
  58. }else{
  59. node.set_icon(-1);
  60. }
  61. }
  62. }

为ListView构造出一个适配器:这个适配器就是经常用到的适配器的写法:

 
  1. /**
  2. * Created by HQOCSHheqing on 2016/8/3.
  3. *
  4. * @description 适配器类,就是listview最常见的适配器写法
  5. */
  6. public class NodeTreeAdapter extends BaseAdapter{
  7. //大家经常用ArrayList,但是这里为什么要使用LinkedList
  8. // ,后面大家会发现因为这个list会随着用户展开、收缩某一项而频繁的进行增加、删除元素操作,
  9. // 因为ArrayList是数组实现的,频繁的增删性能低下,而LinkedList是链表实现的,对于频繁的增删
  10. //操作性能要比ArrayList好。
  11. private LinkedList<Node> nodeLinkedList;
  12. private LayoutInflater inflater;
  13. private int retract;//缩进值
  14. private Context context;
  15. public NodeTreeAdapter(Context context,ListView listView,LinkedList<Node> linkedList){
  16. inflater = LayoutInflater.from(context);
  17. this.context = context;
  18. nodeLinkedList = linkedList;
  19. listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
  20. @Override
  21. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  22. expandOrCollapse(position);
  23. }
  24. });
  25. //缩进值,大家可以将它配置在资源文件中,从而实现适配
  26. retract = (int)(context.getResources().getDisplayMetrics().density*10+0.5f);
  27. }
  28. /**
  29. * 展开或收缩用户点击的条目
  30. * @param position
  31. */
  32. private void expandOrCollapse(int position){
  33. Node node = nodeLinkedList.get(position);
  34. if (node != null && !node.isLeaf()){
  35. boolean old = node.isExpand();
  36. if (old){
  37. List<Node> nodeList = node.get_childrenList();
  38. int size = nodeList.size();
  39. Node tmp = null;
  40. for (int i = 0;i < size;i++){
  41. tmp = nodeList.get(i);
  42. if (tmp.isExpand()){
  43. collapse(tmp,position+1);
  44. }
  45. nodeLinkedList.remove(position+1);
  46. }
  47. }else{
  48. nodeLinkedList.addAll(position + 1, node.get_childrenList());
  49. }
  50. node.setIsExpand(!old);
  51. notifyDataSetChanged();
  52. }
  53. }
  54. /**
  55. * 递归收缩用户点击的条目
  56. * 因为此中实现思路是:当用户展开某一条时,就将该条对应的所有子节点加入到nodeLinkedList
  57. * ,同时控制缩进,当用户收缩某一条时,就将该条所对应的子节点全部删除,而当用户跨级缩进时
  58. * ,就需要递归缩进其所有的孩子节点,这样才能保持整个nodeLinkedList的正确性,同时这种实
  59. * 现方式避免了每次对所有数据进行处理然后插入到一个list,最后显示出来,当数据量一大,就会卡顿,
  60. * 所以这种只改变局部数据的方式性能大大提高。
  61. * @param position
  62. */
  63. private void collapse(Node node,int position){
  64. node.setIsExpand(false);
  65. List<Node> nodes = node.get_childrenList();
  66. int size = nodes.size();
  67. Node tmp = null;
  68. for (int i = 0;i < size;i++){
  69. tmp = nodes.get(i);
  70. if (tmp.isExpand()){
  71. collapse(tmp,position+1);
  72. }
  73. nodeLinkedList.remove(position+1);
  74. }
  75. }
  76. @Override
  77. public int getCount() {
  78. return nodeLinkedList.size();
  79. }
  80. @Override
  81. public Object getItem(int position) {
  82. return nodeLinkedList.get(position);
  83. }
  84. @Override
  85. public long getItemId(int position) {
  86. return position;
  87. }
  88. @Override
  89. public View getView(int position, View convertView, ViewGroup parent) {
  90. final ViewHolder holder;
  91. if (convertView == null){
  92. convertView = inflater.inflate(R.layout.tree_listview_item,null);
  93. holder = new ViewHolder();
  94. holder.imageView = (ImageView)convertView.findViewById(R.id.id_treenode_icon);
  95. holder.label = (TextView)convertView.findViewById(R.id.id_treenode_label);
  96. holder.confirm = (LinearLayout)convertView.findViewById(R.id.id_confirm);
  97. convertView.setTag(holder);
  98. }else{
  99. holder = (ViewHolder)convertView.getTag();
  100. }
  101. Node node = nodeLinkedList.get(position);
  102. holder.label.setText(node.get_label());
  103. if(node.get_icon() == -1){
  104. holder.imageView.setVisibility(View.INVISIBLE);
  105. }else{
  106. holder.imageView.setVisibility(View.VISIBLE);
  107. holder.imageView.setImageResource(node.get_icon());
  108. }
  109. holder.confirm.setTag(position);
  110. holder.confirm.setOnClickListener(new View.OnClickListener() {
  111. @Override
  112. public void onClick(View v) {
  113. Toast.makeText(context,"选中:"+v.getTag(),Toast.LENGTH_SHORT).show();
  114. }
  115. });
  116. convertView.setPadding(node.get_level()*retract,5,5,5);//处理缩进
  117. return convertView;
  118. }
  119. static class ViewHolder{
  120. public ImageView imageView;
  121. public TextView label;
  122. public LinearLayout confirm;
  123. }
  124. }

所有重点都在注释中说明,此处省略。

最后我们来应用一下:

首先创建一个activity:

 
  1. /**
  2. * Created by HQOCSHheqing on 2016/8/4.
  3. *
  4. * @description
  5. */
  6. public class TreeTestActivity extends Activity{
  7. private ListView mListView;
  8. private NodeTreeAdapter mAdapter;
  9. private LinkedList<Node> mLinkedList = new LinkedList<>();
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.select_dept_layout);
  14. mListView = (ListView)findViewById(R.id.id_tree);
  15. mAdapter = new NodeTreeAdapter(this,mListView,mLinkedList);
  16. mListView.setAdapter(mAdapter);
  17. initData();
  18. }
  19. private void initData(){
  20. List<Node> data = new ArrayList<>();
  21. addOne(data);
  22. mLinkedList.addAll(NodeHelper.sortNodes(data));
  23. mAdapter.notifyDataSetChanged();
  24. }
  25. private void addOne(List<Node> data){
  26. data.add(new Dept(1, 0, "总公司"));//可以直接注释掉此项,即可构造一个森林
  27. data.add(new Dept(2, 1, "一级部一级部门一级部门一级部门门级部门一级部门级部门一级部门一级部门门级部一级"));
  28. data.add(new Dept(3, 1, "一级部门"));
  29. data.add(new Dept(4, 1, "一级部门"));
  30. data.add(new Dept(222, 5, "二级部门--测试1"));
  31. data.add(new Dept(223, 5, "二级部门--测试2"));
  32. data.add(new Dept(5, 1, "一级部门"));
  33. data.add(new Dept(224, 5, "二级部门--测试3"));
  34. data.add(new Dept(225, 5, "二级部门--测试4"));
  35. data.add(new Dept(6, 1, "一级部门"));
  36. data.add(new Dept(7, 1, "一级部门"));
  37. data.add(new Dept(8, 1, "一级部门"));
  38. data.add(new Dept(9, 1, "一级部门"));
  39. data.add(new Dept(10, 1, "一级部门"));
  40. for (int i = 2;i <= 10;i++){
  41. for (int j = 0;j < 10;j++){
  42. data.add(new Dept(1+(i - 1)*10+j,i, "二级部门"+j));
  43. }
  44. }
  45. for (int i = 0;i < 5;i++){
  46. data.add(new Dept(101+i,11, "三级部门"+i));
  47. }
  48. for (int i = 0;i < 5;i++){
  49. data.add(new Dept(106+i,22, "三级部门"+i));
  50. }
  51. for (int i = 0;i < 5;i++){
  52. data.add(new Dept(111+i,33, "三级部门"+i));
  53. }
  54. for (int i = 0;i < 5;i++){
  55. data.add(new Dept(115+i,44, "三级部门"+i));
  56. }
  57. for (int i = 0;i < 5;i++){
  58. data.add(new Dept(401+i,101, "四级部门"+i));
  59. }
  60. }
  61. }

布局文件:

#select_dept_layout.xml

 
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent">
  4. <ListView
  5. android:id="@+id/id_tree"
  6. android:layout_width="fill_parent"
  7. android:layout_height="fill_parent"
  8. android:divider="#aaa"
  9. android:dividerHeight="1px"/>
  10. </RelativeLayout>

#tree_listview_item.xml

 
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content">
  5. <ImageView
  6. android:id="@+id/id_treenode_icon"
  7. android:layout_width="wrap_content"
  8. android:layout_height="wrap_content"
  9. android:layout_centerVertical="true"
  10. android:layout_marginLeft="5dp"
  11. android:layout_marginRight="5dp"
  12. android:src="@mipmap/expand" />
  13. <!--保证整块区域可点,使用户好点击-->
  14. <LinearLayout
  15. android:id="@+id/id_confirm"
  16. android:layout_width="wrap_content"
  17. android:layout_height="match_parent"
  18. android:layout_alignParentRight="true"
  19. android:layout_centerVertical="true"
  20. android:clickable="true"
  21. android:paddingBottom="8dp"
  22. android:paddingLeft="15dp"
  23. android:paddingRight="15dp"
  24. android:paddingTop="8dp">
  25. <ImageView
  26. android:layout_width="25dp"
  27. android:layout_height="25dp"
  28. android:background="@drawable/login_checkbox_selector"
  29. android:scaleType="centerInside" />
  30. </LinearLayout>
  31. <TextView
  32. android:id="@+id/id_treenode_label"
  33. android:layout_width="wrap_content"
  34. android:layout_height="wrap_content"
  35. android:layout_centerVertical="true"
  36. android:layout_toLeftOf="@id/id_confirm"
  37. android:layout_toRightOf="@id/id_treenode_icon"
  38. android:textColor="@android:color/black"
  39. android:textSize="12sp" />
  40. </RelativeLayout>

实现思路:

 
  1. 要实现一个层级显示的控件,但是又不确定有几层,而内置的ExpandableListView又只能显示两级关系,所以只能自己改造已有的控件或者完全自己写,但是再仔细考虑会发现这两种方式都不太好实现,都需要我们自己处理层级,而且完全自己写还有一个致命问题就是复用问题,即使实现了也会有很多bug,想想会让我们无从下手。但是我们换一种思路,要想展示层级关系,不就是父级与子级之间的缩进不同吗,所以我们是否可以通过控制ListView的各个条目的缩进从而达到这个目的,这样我们就不用管复杂的复用问题了,但是怎么才能实现一层一层的展开、收缩呢?不要想的太复杂,换一种思路,其实就是更改ListView的数据集,展开时将要展开的数据放入到数据集中,收缩时从数据集中删除相应数据即可,这样我们每次只处理与用户点击有关的局部数据,而不用每次遍历所有的数据进行筛选,这样性能会大大提高。
  2. 在实现这个功能之前也上网找了资料,其中深受这篇博客(http://blog.csdn.net/lmj623565791/article/details/40212367)的启发,是站在巨人的肩膀上,在此感谢。
  3. 完整源代码:[http://download.csdn.net/detail/hqocshheqing/9601185][http_download.csdn.net_detail_hqocshheqing_9601185]
  4. github地址:[https://github.com/heqinghqocsh/TreeView][https_github.com_heqinghqocsh_TreeView]

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Centos7部署Python3环境

一、安装Python3 ###查看是否安装Python3 Centos 7 默认安装了python 2.7.5. 因为一些命令要用它比如yum 它使用的是python2.7.5 使用 python -V 命令查看一下是否安装Python 然后使用命令 which python 查看一下Python可执行文件的位置 Python指向的是Python2.7 安装依赖 y…

Eolink Apikit 版本更新:「数据字典」功能上线、支持 MongoDB 数据库操作、金融行业私有化协议、GitLab 生成 API 文档...

&#x1f389; 新增 搭建自定义接口协议架构&#xff0c;支持快速适配金融行业各类型私有协议的导入、编辑和展示。 数据字典功能上线&#xff0c;支持以数据字典的形式管理参数枚举值&#xff1b; 数据库连接支持 MongoDB 数据库操作&#xff1b; 基于 Apikit 类型导入 API…

微服务之Eureka

文章目录 一、Eureka介绍1.Eureka的作用2.总结 二.搭建Eureka服务端步骤1.导入maven依赖2.编写启动类&#xff0c;添加EnableEurekaServer注解3.添加application.yml文件&#xff0c;编写下面的配置&#xff1a; 三.注册Eureka客户端服务提供者&#xff08;user-service&#x…

Modelsim 使用教程(5)——Analyzing Waveforms

一、概述 Wave窗口允许我们以HDL波形和数据的形式查看仿真结果。Wave窗口被划分为多个窗格。通过单击并在任意两个窗格之间拖动该条&#xff0c;可以调整路径名窗格、值窗格和波形窗格的大小。 二、加载一个设计&#xff08;Loading a Design&#xff09; 1、打开modelsim 2、…

前端之Bootstrap框架

目录 【一】Bootstrap介绍 【二】Bootstrap引入 【1】CDN加速链接 【2】注意 【三】布局容器 【四】栅格系统 【五】栅格参数 【六】列偏移 【七】排版 标题 内联文本元素 对齐 改变大小写 引用 列表 【八】表格 基本实例 条纹状表格 带边框的表格 鼠标悬停…

[量化投资-学习笔记006]Python+TDengine从零开始搭建量化分析平台-MACD

在上一章节介绍了 EMA 均线的计算&#xff0c;本节主要介绍均线的进化形态之一&#xff1a;MACD MACD (Moving Average Convergence / Divergence) 指数平滑移动平均线。MACD 是通过计算不同时间的 EMA 的差值俩判断价格趋势。 MACD 包括 3 个值&#xff1a; 长短期 EMA 差值…

Ubuntu 22.04.3 LTS中安装singularity

文章目录 概要背景知识什么是singularity ? 安装流程1. 安装Go2. 下载Singularity3. 编译Singularity源代码 4. 验证安装是否成功singularity的使用安装open structure 小结 概要 这里主要记录singularity的安装和使用&#xff0c;安装过程中会出现相关的错误&#xff0c;所以…

[C/C++]数据结构 链表OJ题: 链表分割

题目描述: 现有一链表的头指针 ListNode* pHead&#xff0c;给一定值x&#xff0c;编写一段代码将所有小于x的结点排在其余结点之前&#xff0c;且不能改变原来的数据顺序&#xff0c;返回重新排列后的链表的头指针。 解题思路: 创建两个新链表,head1,head2, 遍历原链表,把小于…

RISC-V与RISC Zero zkVM的关系

1. 引言 本文基本结构为&#xff1a; 编程语言背景介绍RISC-V虚拟机作为zkVM电路为何选择RISC-V&#xff1f; 2. 编程语言背景介绍 高级编程语言不专门针对某个架构&#xff0c;其便于人类编写。高级编程语言代码&#xff0c;经编译器编译后&#xff0c;会生成针对专门某架…

JAR 文件规范详解

介绍 JAR文件是基于ZIP文件格式的一种文件格式&#xff0c;用来将许多文件整合成一个文件。一个JAR文件本质上是包含可选目录META-INF的zip文件&#xff0c;可以通过命令行jar工具或者在Java平台上使用java.util.jar中的API来创建。JAR文件的命名没有严格的要求&#xff0c;可…

详解 SpringMVC 的 HttpMessageConverter

文章目录 前言参考资料内容1、[RequestBody ](/RequestBody )2、RequestEntity3、[ResponseBody ](/ResponseBody )4、SpringMVC处理json5、SpringMVC处理ajax6、RestController注解7、ResponseEntity 推荐读物 《Spring Boot微服务实战(第2版)》内容简介目录 前言 HttpMessag…

【Agent模型1】MemGPT: Towards LLMs as Operating Systems

论文标题&#xff1a;MemGPT: Towards LLMs as Operating Systems 论文作者&#xff1a;Charles Packer, Vivian Fang, Shishir G. Patil, Kevin Lin, Sarah Wooders, Joseph E. Gonzalez (UC Berkeley) 论文原文&#xff1a;https://arxiv.org/abs/2310.08560 论文出处&#x…

Android Studio报错:connect refused

参考链接&#xff1a; https://blog.csdn.net/qq_43213783/article/details/113936012 参考文章中说报错主要是由于代理导致的&#xff0c;在文件->设置->外观与行为->系统设置->HTTP代理。 方法一&#xff1a; 查看打开代理&#xff08;前提是代理可以通网&#x…

Microsoft Dynamics 365 CE 扩展定制 - 8. DevOps

在本章中,我们将介绍以下内容: 使用PowerShell导出Dynamics 365解决方案使用PowerShell部署解决方案构建解决方案层次结构修补解决方案暂存解决方案使用SolutionPackager在源代码管理中保存解决方案使用PackageDeployer将您的解决方案与配置数据打包基于解决方案版本增量触发…

CSS 滚动捕获 Scroll Snap

CSS 滚动捕获 Scroll Snap CSS 滚动捕获允许开发者通过声明一些位置(或叫作捕获位置)来创建精准控制的滚动体验. 通常来说轮播图就是这种体验的例子, 在轮播图中, 用户只能停在图 A 或者图 B, 而不能停在 A 和 B 的中间. 比如平时用淘宝或小红书, 当你上滑到下一个推荐内容时…

Linux Crontab 定时任务

crond 服务 Linux 通过 crond 服务来支持 crontab。 查看 crond 服务是否已经安装 输入下面命令确认 crond 服务是否已安装。 systemctl list-unit-files | grep crond 如果为 enabled&#xff0c;表示服务正运行。 crontab 文件 crontab 要执行的定时任务都被保存在 /etc…

Vue3:解决基地址不同 数据交互http与https跨域问题

配置公共管理的api文件和vue.config.js可以解决跨域问题。一个项目对接不同的基地址和接口同理。 api export default {//接口基地址Millia: process.env.NODE_ENV development ? location.protocol // location.host /milliaApi : http://xx.xxx.xxxx/index.php/,Milli…

CSS 浮动

目标target✓ 能够说出来为什么需要浮动能够说出来浮动的排列特性能够说出来三种最常见的布局方式能够说出来为什么需要清除浮动,能够至少写出两种清楚浮动的方法能够利用Photoshop实现基本的切图能够利用Photoshop插件实现切图能够完成学成在线的页面布 传统网页布局的三种模…

视频增强和修复工具 Topaz Video AI mac中文版功能

Topaz Video AI mac是一款使用人工智能技术对视频进行增强和修复的软件。它可以自动降噪、去除锐化、减少压缩失真、提高清晰度等等。Topaz Video AI可以处理各种类型的视频&#xff0c;包括低分辨率视频、老旧影片、手机录制的视频等。 使用Topaz Video AI非常简单&#xff0c…

03【保姆级】-GO语言变量和数据类型和相互转换

03【保姆级】-GO语言变量和数据类型 一、变量1.1 变量的定义&#xff1a;1.2 变量的声明、初始化、赋值1.3 变量使用的注意事项 插播-关于fmt.Printf格式打印%的作用二、 变量的数据类型2.1整数的基本类型2.1.1 有符号类型 int8/16/32/642.1.2 无符号类型 int8/16/32/642.1.3 整…