从源码学习UEToll

  • 捕获控件梳理
  • 相对位置功能梳理
  • 网格栅栏功能梳理

捕获代码分析

TransparentActivity

  1. public @interface Type {
  2. int TYPE_UNKNOWN = -1;
  3. int TYPE_EDIT_ATTR = 1; // 捕获控件
  4. int TYPE_SHOW_GRIDDING = 2; // 网格
  5. int TYPE_RELATIVE_POSITION = 3; // 相对位置
  6. }
  7. @Override
  8. protected void onCreate(Bundle savedInstanceState) {
  9. super.onCreate(savedInstanceState);
  10. /// 省略代码
  11. type = getIntent().getIntExtra(EXTRA_TYPE, TYPE_UNKNOWN);
  12. switch (type) {
  13. case TYPE_EDIT_ATTR: // 捕获控件的入口
  14. EditAttrLayout editAttrLayout = new EditAttrLayout(this);
  15. editAttrLayout.setOnDragListener(new EditAttrLayout.OnDragListener() {
  16. @Override
  17. public void showOffset(String offsetContent) {
  18. board.updateInfo(offsetContent); //更新左下角展示的view描述
  19. }
  20. });
  21. vContainer.addView(editAttrLayout);
  22. break;
  23. }
  24. }

EditAttrLayout

  1. public class EditAttrLayout extends CollectViewsLayout {
  2. private Element targetElement;
  3. private AttrsDialog dialog;
  4. private IMode mode = new ShowMode();
  5. private float lastX, lastY;
  6. private OnDragListener onDragListener;
  7. @Override
  8. protected void onDraw(Canvas canvas) {
  9. super.onDraw(canvas);
  10. if (targetElement != null) {
  11. canvas.drawRect(targetElement.getRect(), areaPaint);
  12. mode.onDraw(canvas); // 进行mode的draw
  13. }
  14. }
  15. @Override
  16. public boolean onTouchEvent(MotionEvent event) {
  17. switch (event.getAction()) {
  18. case MotionEvent.ACTION_DOWN:
  19. lastX = event.getX();
  20. lastY = event.getY();
  21. break;
  22. case MotionEvent.ACTION_UP:
  23. mode.triggerActionUp(event); // 调用ShowMode.triggerActionUp(默认),可更改为MoveMode.triggerActionUp
  24. break;
  25. case MotionEvent.ACTION_MOVE:
  26. mode.triggerActionMove(event); // 移动view时触发的方法
  27. break;
  28. }
  29. return true;
  30. }
  31. class ShowMode implements IMode {
  32. @Override
  33. public void onDraw(Canvas canvas) {
  34. Rect rect = targetElement.getRect();
  35. drawLineWithText(canvas, rect.left, rect.top - lineBorderDistance, rect.right, rect.top - lineBorderDistance);
  36. drawLineWithText(canvas, rect.right + lineBorderDistance, rect.top, rect.right + lineBorderDistance, rect.bottom);
  37. }
  38. @Override
  39. public void triggerActionMove(MotionEvent event) {
  40. }
  41. @Override
  42. public void triggerActionUp(final MotionEvent event) {
  43. // 在按下抬起的时候 获取到event,并生成element
  44. final Element element = getTargetElement(event.getX(), event.getY());
  45. if (element != null) {
  46. targetElement = element; // 赋值给当前元素
  47. invalidate(); // 请求重绘View树,即draw()过程
  48. if (dialog == null) {
  49. dialog = new AttrsDialog(getContext());
  50. dialog.setAttrDialogCallback(new AttrsDialog.AttrDialogCallback() {
  51. // 里面的回调我们先不关心,现在只关心bottom弹出部分
  52. });
  53. }
  54. dialog.show(targetElement); // 弹出展示页面
  55. }
  56. }
  57. }
  58. }

AttrsDialog

  1. public class AttrsDialog extends Dialog {
  2. private RecyclerView vList; // bottom view
  3. private Adapter adapter = new Adapter();
  4. public void show(Element element) {
  5. show(); // Dialog.show()
  6. // ... 省略些window配置
  7. adapter.notifyDataSetChanged(element); // 更新bottom view
  8. layoutManager.scrollToPosition(0);
  9. }
  10. }

到这里发现只是更新了adapter数据,那接下来就应该去adapter里面去找数据的来源了.

adapter代码太多了了截取了相关代码进行展示

AttrsDialog.Adapter

  1. public static class Adapter extends RecyclerView.Adapter {
  2. private List<Item> items = new ItemArrayList<>();
  3. private AttrDialogCallback callback;
  4. // 更新item数据
  5. public void notifyDataSetChanged(Element element) {
  6. items.clear();
  7. for (String attrsProvider : UETool.getInstance().getAttrsProvider()) {
  8. try {
  9. IAttrs attrs = (IAttrs) Class.forName(attrsProvider).newInstance();
  10. items.addAll(attrs.getAttrs(element)); // 这里获取的数据
  11. } catch (Exception e) {
  12. e.printStackTrace();
  13. }
  14. }
  15. notifyDataSetChanged();
  16. }
  17. }

可以发现数据都是通过IAttrs.getAttrs(element)获取的.接下来就Ctrl+Alt+鼠标左键找到了UETCore/UETTextView/UETImageView,

它们都实现了IAttrs类.由下面的代码就可以知道item的数据是从哪里来的了.

  1. 先是获取到element的view
  2. 通过AttrsManager.createAttrs(view)获取自定义view的属性,并且进行填充
  3. 针对不同的属性填充不同的item,对应的值从view中获取
  4. 最后返回一个总属性的List<item>

UETCore

  1. public class UETCore implements IAttrs {
  2. @Override
  3. public List<Item> getAttrs(Element element) {
  4. List<Item> items = new ArrayList<>();
  5. View view = element.getView();
  6. items.add(new SwitchItem("Move", element, SwitchItem.Type.TYPE_MOVE));
  7. items.add(new SwitchItem("ValidViews", element, SwitchItem.Type.TYPE_SHOW_VALID_VIEWS));
  8. IAttrs iAttrs = AttrsManager.createAttrs(view);
  9. if (iAttrs != null) {
  10. items.addAll(iAttrs.getAttrs(element));
  11. }
  12. items.add(new TitleItem("COMMON"));
  13. items.add(new TextItem("Class", view.getClass().getName()));
  14. items.add(new TextItem("Id", Util.getResId(view)));
  15. items.add(new TextItem("ResName", Util.getResourceName(view.getId())));
  16. items.add(new TextItem("Clickable", Boolean.toString(view.isClickable()).toUpperCase()));
  17. items.add(new TextItem("Focused", Boolean.toString(view.isFocused()).toUpperCase()));
  18. items.add(new AddMinusEditItem("Width(dp)", element, EditTextItem.Type.TYPE_WIDTH, px2dip(view.getWidth())));
  19. items.add(new AddMinusEditItem("Height(dp)", element, EditTextItem.Type.TYPE_HEIGHT, px2dip(view.getHeight())));
  20. items.add(new TextItem("Alpha", String.valueOf(view.getAlpha())));
  21. Object background = Util.getBackground(view);
  22. if (background instanceof String) {
  23. items.add(new TextItem("Background", (String) background));
  24. } else if (background instanceof Bitmap) {
  25. items.add(new BitmapItem("Background", (Bitmap) background));
  26. }
  27. items.add(new AddMinusEditItem("PaddingLeft(dp)", element, EditTextItem.Type.TYPE_PADDING_LEFT, px2dip(view.getPaddingLeft())));
  28. items.add(new AddMinusEditItem("PaddingRight(dp)", element, EditTextItem.Type.TYPE_PADDING_RIGHT, px2dip(view.getPaddingRight())));
  29. items.add(new AddMinusEditItem("PaddingTop(dp)", element, EditTextItem.Type.TYPE_PADDING_TOP, px2dip(view.getPaddingTop())));
  30. items.add(new AddMinusEditItem("PaddingBottom(dp)", element, EditTextItem.Type.TYPE_PADDING_BOTTOM, px2dip(view.getPaddingBottom())));
  31. return items;
  32. }
  33. static class AttrsManager {
  34. public static IAttrs createAttrs(View view) {
  35. if (view instanceof TextView) {
  36. return new UETTextView();
  37. } else if (view instanceof ImageView) {
  38. return new UETImageView();
  39. }
  40. return null;
  41. }
  42. }
  43. static class UETTextView implements IAttrs {
  44. @Override
  45. public List<Item> getAttrs(Element element) {
  46. List<Item> items = new ArrayList<>();
  47. TextView textView = ((TextView) element.getView());
  48. items.add(new TitleItem("TextView"));
  49. items.add(new EditTextItem("Text", element, EditTextItem.Type.TYPE_TEXT, textView.getText().toString()));
  50. items.add(new AddMinusEditItem("TextSize(sp)", element, EditTextItem.Type.TYPE_TEXT_SIZE, px2sp(textView.getTextSize())));
  51. items.add(new EditTextItem("TextColor", element, EditTextItem.Type.TYPE_TEXT_COLOR, Util.intToHexColor(textView.getCurrentTextColor())));
  52. List<Pair<String, Bitmap>> pairs = Util.getTextViewBitmap(textView);
  53. for (Pair<String, Bitmap> pair : pairs) {
  54. items.add(new BitmapItem(pair.first, pair.second));
  55. }
  56. items.add(new SwitchItem("IsBold", element, SwitchItem.Type.TYPE_IS_BOLD, textView.getTypeface() != null ? textView.getTypeface().isBold() : false));
  57. return items;
  58. }
  59. }
  60. static class UETImageView implements IAttrs {
  61. @Override
  62. public List<Item> getAttrs(Element element) {
  63. List<Item> items = new ArrayList<>();
  64. ImageView imageView = ((ImageView) element.getView());
  65. items.add(new TitleItem("ImageView"));
  66. items.add(new BitmapItem("Bitmap", Util.getImageViewBitmap(imageView)));
  67. items.add(new TextItem("ScaleType", Util.getImageViewScaleType(imageView)));
  68. return items;
  69. }
  70. }
  71. }

那么element从哪里来的呢

  1. // AttrsDialog
  2. public void show(Element element) {
  3. show();
  4. Window dialogWindow = getWindow();
  5. WindowManager.LayoutParams lp = dialogWindow.getAttributes();
  6. dialogWindow.setGravity(Gravity.LEFT | Gravity.TOP);
  7. lp.x = element.getRect().left;
  8. lp.y = element.getRect().bottom;
  9. lp.width = getScreenWidth() - dip2px(30);
  10. lp.height = getScreenHeight() / 2;
  11. dialogWindow.setAttributes(lp);
  12. adapter.notifyDataSetChanged(element); //这里传递给adapter的
  13. layoutManager.scrollToPosition(0);
  14. }
  15. // EditAttrLayout.ShowMode
  16. public void triggerActionUp(final MotionEvent event) {
  17. final Element element = getTargetElement(event.getX(), event.getY());
  18. if (element != null) {
  19. targetElement = element;
  20. invalidate();
  21. if (dialog == null) {
  22. dialog = new AttrsDialog(getContext());
  23. dialog.setAttrDialogCallback(new AttrsDialog.AttrDialogCallback() {
  24. @Override
  25. public void enableMove() {
  26. mode = new MoveMode();
  27. dialog.dismiss();
  28. }
  29. @Override
  30. public void showValidViews(int position, boolean isChecked) {
  31. int positionStart = position + 1;
  32. if (isChecked) {
  33. dialog.notifyValidViewItemInserted(positionStart, getTargetElements(lastX, lastY), targetElement);
  34. } else {
  35. dialog.notifyItemRangeRemoved(positionStart);
  36. }
  37. }
  38. @Override
  39. public void selectView(Element element) {
  40. targetElement = element;
  41. dialog.dismiss();
  42. dialog.show(targetElement);
  43. }
  44. });
  45. dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
  46. @Override
  47. public void onDismiss(DialogInterface dialog) {
  48. if (targetElement != null) {
  49. targetElement.reset();
  50. invalidate();
  51. }
  52. }
  53. });
  54. }
  55. dialog.show(targetElement);
  56. }
  57. }

就会发现重点在getTargetElement方法里面,所有更新adapter的操作都走了这个方法.

跟踪上去

  1. protected Element getTargetElement(float x, float y) {
  2. Element target = null;
  3. for (int i = elements.size() - 1; i >= 0; i--) {
  4. final Element element = elements.get(i);
  5. if (element.getRect().contains((int) x, (int) y)) {
  6. if (isParentNotVisible(element.getParentElement())) {
  7. continue;
  8. }
  9. if (element != childElement) {
  10. childElement = element;
  11. parentElement = element;
  12. } else if (parentElement != null) {
  13. parentElement = parentElement.getParentElement();
  14. }
  15. target = parentElement;
  16. break;
  17. }
  18. }
  19. if (target == null) {
  20. Toast.makeText(getContext(), getResources().getString(R.string.uet_target_element_not_found, x, y), Toast.LENGTH_SHORT).show();
  21. }
  22. return target;
  23. }

发现跟elements这个数组有关系

  1. // CollectViewsLayout
  2. private void traverse(View view) {
  3. if (UETool.getInstance().getFilterClasses().contains(view.getClass().getName())) return;
  4. if (view.getAlpha() == 0 || view.getVisibility() != View.VISIBLE) return;
  5. if (getResources().getString(R.string.uet_disable).equals(view.getTag())) return;
  6. elements.add(new Element(view));
  7. if (view instanceof ViewGroup) {
  8. ViewGroup parent = (ViewGroup) view;
  9. for (int i = 0; i < parent.getChildCount(); i++) {
  10. traverse(parent.getChildAt(i));
  11. }
  12. }
  13. }
  14. @Override
  15. protected void onAttachedToWindow() {
  16. super.onAttachedToWindow();
  17. try {
  18. Activity targetActivity = UETool.getInstance().getTargetActivity();
  19. WindowManager windowManager = targetActivity.getWindowManager();
  20. Field mGlobalField = Class.forName("android.view.WindowManagerImpl").getDeclaredField("mGlobal");
  21. mGlobalField.setAccessible(true);
  22. if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
  23. Field mViewsField = Class.forName("android.view.WindowManagerGlobal").getDeclaredField("mViews");
  24. mViewsField.setAccessible(true);
  25. List<View> views = (List<View>) mViewsField.get(mGlobalField.get(windowManager));
  26. for (int i = views.size() - 1; i >= 0; i--) {
  27. View targetView = getTargetDecorView(targetActivity, views.get(i));
  28. if (targetView != null) {
  29. traverse(targetView);
  30. break;
  31. }
  32. }
  33. } else {
  34. Field mRootsField = Class.forName("android.view.WindowManagerGlobal").getDeclaredField("mRoots");
  35. mRootsField.setAccessible(true);
  36. List viewRootImpls;
  37. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
  38. viewRootImpls = (List) mRootsField.get(mGlobalField.get(windowManager));
  39. } else {
  40. viewRootImpls = Arrays.asList((Object[]) mRootsField.get(mGlobalField.get(windowManager)));
  41. }
  42. for (int i = viewRootImpls.size() - 1; i >= 0; i--) {
  43. Class clazz = Class.forName("android.view.ViewRootImpl");
  44. Object object = viewRootImpls.get(i);
  45. Field mWindowAttributesField = clazz.getDeclaredField("mWindowAttributes");
  46. mWindowAttributesField.setAccessible(true);
  47. Field mViewField = clazz.getDeclaredField("mView");
  48. mViewField.setAccessible(true);
  49. View decorView = (View) mViewField.get(object);
  50. WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams) mWindowAttributesField.get(object);
  51. if (layoutParams.getTitle().toString().contains(targetActivity.getClass().getName())
  52. || getTargetDecorView(targetActivity, decorView) != null) {
  53. traverse(decorView);
  54. break;
  55. }
  56. }
  57. }
  58. } catch (Exception e) {
  59. e.printStackTrace();
  60. }
  61. }

发现这个方法通过反射获取到应用的mViews,然后循环找到当前ActivitydecorView,

然后递归traverse方法获取到所有的子view,填充到elements中,最后被getTargetElement获取出来.

然后基本上就这样了.

总结-流程

  1. UETMenu.show()window层面展示一个悬浮框
  2. 点击第一个按钮捕获控件,跳转到TransparentActivity
  3. 根据typeActivityvContainer添加EditAttrLayout
  4. EditAttrLayoutMotionEvent.ACTION_UP事件触发的时候就执行ShowModeltriggerActionUp,弹出AttrsDialog,用于展示相关View的信息
  5. View的详细信息在UETCore中获取
  6. 这时候注意到adapteritems的数据是由show(element)传递进来的
  7. showelementgetTargetElement()方法提供的
  8. getTargetElement中可以看到有个elements,再找到他的源头->traverse->onAttachedToWindow

捕获代码并且展示的这一部分就差不多了.大致流程应该梳理的还算清楚了.

相对位置分析

TransparentActivity

  1. protected void onCreate(Bundle savedInstanceState) {
  2. super.onCreate(savedInstanceState);
  3. ...
  4. switch (type) {
  5. case TYPE_EDIT_ATTR:
  6. ...
  7. case TYPE_RELATIVE_POSITION:
  8. // 这个是入口,将一个RelativePositionLayout,添加到了
  9. // R.id.container 里面
  10. vContainer.addView(new RelativePositionLayout(this));
  11. break;
  12. case TYPE_SHOW_GRIDDING:
  13. ...
  14. default:
  15. ...
  16. }
  17. ...
  18. }

RelativePositionLayout

  1. private final int elementsNum = 2; // 指定View个数为2个
  2. // View
  3. private Element[] relativeElements = new Element[elementsNum];
  4. private int searchCount = 0; // 搜索次数,也就是你点击View的次数
  5. @Override
  6. public boolean onTouchEvent(MotionEvent event) {
  7. switch (event.getAction()) {
  8. case MotionEvent.ACTION_DOWN:
  9. break;
  10. case MotionEvent.ACTION_UP:
  11. // 在这里处理View的逻辑,被整除的在第一个,否则在第二个,同时
  12. // searchCount累加
  13. final Element element = getTargetElement(event.getX(), event.getY());
  14. if (element != null) {
  15. relativeElements[searchCount % elementsNum] = element;
  16. searchCount++;
  17. invalidate();
  18. }
  19. break;
  20. }
  21. return true;
  22. }
  23. @Override
  24. protected void onDraw(Canvas canvas) {
  25. super.onDraw(canvas);
  26. if (relativeElements == null) {
  27. return;
  28. }
  29. boolean doubleNotNull = true;
  30. for (Element element : relativeElements) {
  31. // (1)
  32. if (element != null) {
  33. Rect rect = element.getRect();
  34. canvas.drawLine(0, rect.top, screenWidth, rect.top, dashLinePaint);
  35. canvas.drawLine(0, rect.bottom, screenWidth, rect.bottom, dashLinePaint);
  36. canvas.drawLine(rect.left, 0, rect.left, screenHeight, dashLinePaint);
  37. canvas.drawLine(rect.right, 0, rect.right, screenHeight, dashLinePaint);
  38. canvas.drawRect(rect, areaPaint);
  39. } else {
  40. doubleNotNull = false;
  41. }
  42. }
  43. if (doubleNotNull) {
  44. // (2)
  45. Rect firstRect = relativeElements[searchCount % elementsNum].getRect();
  46. Rect secondRect = relativeElements[(searchCount - 1) % elementsNum].getRect();
  47. if (secondRect.top > firstRect.bottom) {
  48. int x = secondRect.left + secondRect.width() / 2;
  49. drawLineWithText(canvas, x, firstRect.bottom, x, secondRect.top);
  50. }
  51. if (firstRect.top > secondRect.bottom) {
  52. int x = secondRect.left + secondRect.width() / 2;
  53. drawLineWithText(canvas, x, secondRect.bottom, x, firstRect.top);
  54. }
  55. if (secondRect.left > firstRect.right) {
  56. int y = secondRect.top + secondRect.height() / 2;
  57. drawLineWithText(canvas, secondRect.left, y, firstRect.right, y);
  58. }
  59. if (firstRect.left > secondRect.right) {
  60. int y = secondRect.top + secondRect.height() / 2;
  61. drawLineWithText(canvas, secondRect.right, y, firstRect.left, y);
  62. }
  63. drawNestedAreaLine(canvas, firstRect, secondRect);
  64. drawNestedAreaLine(canvas, secondRect, firstRect);
  65. }
  66. }

onDraw中的逻辑

  1. 初始化时doubleNotNull返回false,直接跳过onDraw的逻辑.
  2. 当点击第一个View时.走标记为(1)处代码,为View绘画边框线和虚线,同时doubleNotNull返回false,跳过onDraw.
  3. 当有两个View时.走标记为(2)处代码,计算两个View的相对位置然后根据不同情况画线.

网格栅栏分析

TransparentActivity

  1. protected void onCreate(Bundle savedInstanceState) {
  2. super.onCreate(savedInstanceState);
  3. ...
  4. switch (type) {
  5. case TYPE_EDIT_ATTR:
  6. ...
  7. case TYPE_RELATIVE_POSITION:
  8. ...
  9. case TYPE_SHOW_GRIDDING:
  10. // 这个是入口,将一个GriddingLayout,添加到了
  11. // R.id.container 里面
  12. vContainer.addView(new GriddingLayout(this));
  13. board.updateInfo("LINE_INTERVAL: " + DimenUtil.px2dip(GriddingLayout.LINE_INTERVAL, true));
  14. default:
  15. ...
  16. }
  17. ...
  18. }

这里就是简单的添加了一个间隔为5dp网格View.

从源码学习UEToll的更多相关文章

  1. Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结

    2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash--系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度.唯品会.58同城.新浪微博.趣分 ...

  2. jQuery源码学习感想

    还记得去年(2015)九月份的时候,作为一个大四的学生去参加美团霸面,结果被美团技术总监教育了一番,那次问了我很多jQuery源码的知识点,以前虽然喜欢研究框架,但水平还不足够来研究jQuery源码, ...

  3. MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)

    前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...

  4. MVC系列——MVC源码学习:打造自己的MVC框架(三:自定义路由规则)

    前言:上篇介绍了下自己的MVC框架前两个版本,经过两天的整理,版本三基本已经完成,今天还是发出来供大家参考和学习.虽然微软的Routing功能已经非常强大,完全没有必要再“重复造轮子”了,但博主还是觉 ...

  5. MVC系列——MVC源码学习:打造自己的MVC框架(二:附源码)

    前言:上篇介绍了下 MVC5 的核心原理,整篇文章比较偏理论,所以相对比较枯燥.今天就来根据上篇的理论一步一步进行实践,通过自己写的一个简易MVC框架逐步理解,相信通过这一篇的实践,你会对MVC有一个 ...

  6. MVC系列——MVC源码学习:打造自己的MVC框架(一:核心原理)

    前言:最近一段时间在学习MVC源码,说实话,研读源码真是一个痛苦的过程,好多晦涩的语法搞得人晕晕乎乎.这两天算是理解了一小部分,这里先记录下来,也给需要的园友一个参考,奈何博主技术有限,如有理解不妥之 ...

  7. 我的angularjs源码学习之旅2——依赖注入

    依赖注入起源于实现控制反转的典型框架Spring框架,用来削减计算机程序的耦合问题.简单来说,在定义方法的时候,方法所依赖的对象就被隐性的注入到该方法中,在方法中可以直接使用,而不需要在执行该函数的时 ...

  8. ddms(基于 Express 的表单管理系统)源码学习

    ddms是基于express的一个表单管理系统,今天抽时间看了下它的代码,其实算不上源码学习,只是对它其中一些小的开发技巧做一些记录,希望以后在项目开发中能够实践下. 数据层封装 模块只对外暴露mod ...

  9. leveldb源码学习系列

    楼主从2014年7月份开始学习<>,由于书籍比较抽象,为了加深思考,同时开始了Google leveldb的源码学习,主要是想学习leveldb的设计思想和Google的C++编程规范.目 ...

随机推荐

  1. 百度Paddle速查_CPU和GPU的mnist预测训练_模型导出_模型导入再预测_导出onnx并预测

    需要做点什么 方便广大烟酒生研究生.人工智障炼丹师算法工程师快速使用百度PaddelPaddle,所以特写此文章,默认使用者已有基本的深度学习概念.数据集概念. 系统环境 python 3.7.4 p ...

  2. BZOJ3159: 决战(FHQ Treap)

    传送门: 解题思路: 算是补坑了,这题除了Invert以外就可以树剖线段树解决了. 考虑Invert操作,延续先前树链剖分的做法,考虑先前算法的瓶颈. 最暴力的方法是暴力交换权值,然而这种方法忽略了当 ...

  3. 查找bug的一些经验总结

    项目开发中遇到的bug解决经验总结 今天在项目开发中遇到了两个很难解决的bug,我把我的思路记录下来,以供之后遇到bug时,提供一些思路: 编译通过,但总结"core dumped" ...

  4. Java 中的 final 关键字有哪些用法?

    修饰类:表示该类不能被继承: 修饰方法:表示方法不能被重写: 修饰变量:表示变量只能一次赋值以后值不能被修改(常量).

  5. 转:怎样理解OOP?OOP又是什么?

    本文转载至:https://blog.csdn.net/q34323201/article/details/80198271. OOP面向对象编程.OOP思想中很重要的有五点,类,对象,还有面向对象的 ...

  6. 读懂jstack

    1 jstack jstack是JDK自带的一种线程栈跟踪工具,用于生成java虚拟机当前时刻线程快照.在定位线程卡顿.死锁.block等原因的时候非常有用.使用方法是: jstack [-l] pi ...

  7. SaltStack项目实战(二)

    架构图: 配置思路 (1).系统初始化 Base环境下存放所有系统都要执行的状态,调整内核参数,dns,装zabbix-agent等 (2).功能模块(如:上面的haproxy) 如上面的haprox ...

  8. 学习ELK日志平台(三)

    ELK(elasticsearch.logstash.kibana) Elastic Stack是原ELK Stack在5.0版本加入Beats套件后的新称呼 解决痛点: 开发人员不能登录线上serv ...

  9. 学习MFS(四)

    一.搭建Master Server 1.安装相关编译器.工具包 [root@master ~]# yum -y install gcc gcc-c++ zlib-devel 2.创建进程用户 [roo ...

  10. 攻防世界PHP2

    PHP2 进入环境就一个英文其他啥都没有,英文也没啥提示信息 我们使用dirsearch扫描一下,一开始确实没扫到什么东西,到最后看了wp发现原来源码是在index.phps中,这里只提供一个思路,不 ...