How to quickly determine the implementation of a competing product interface?

When you receive a product whose requirement is to imitate a competing product and the time is short and there is not much time for you to investigate the technical solution, how to determine the technical solution of this function as soon as possible? Here I give my own tips, can avoid detachments, such as the first to determine the scheme to find a variety of reasons at the end of the scheme is not good, resulting in the final temporary change of the scheme, delayed release of the tragedy of demand… ,

  • Android\ SDK \ Tools first go to this directory to find the monitor executable, then open the page of the competing product you want to emulate, and execute this file

For example, the main interface of Douyin sliding the whole screen, I believe that many people have not done before, many people may think that recyclerView can be used to do this scene, in fact, recyclerView can be done, but Douyin can be seen here is to use viewpager to do. As an imitator, we obviously preferred viewPager in order to avoid missteps.

  • Secondly, with this software, you can also see the id of a control on the interface. This ID is very important, later when we decompile we can find the source code through the global search id, although it is confused with the code, but still can roughly analyze some technical details. A note here: When you use this method to analyze the interface of many Ali products, you will find that there is no ID to capture. Rest assured, this is not an Ali hack technology anti-decompilation technology, but ali uses a similar solution such as Weex React Native. When using this solution, we cannot find the ID. If you know the weex React-Native implementation in general you know what I’m talking about, right

  • Decompilation using JADX is enough. By decompilating with JADX and searching for your previous ID, I can roughly find the corresponding code location. This is how I determined which open source control on Github the vertical viewpager used by Douyin came from… In order to avoid legal disputes, I will not say which open source vertical sliding viewpager is used here, but if you are interested, you can play it for yourself.

  • The adb shell dumpsys activity | grep mFocusedActivity artifact, this command is to you are according to the current type the name of the activity, you can more quickly locate competing goods code..

This can be useful if you don't know if a competitor is launching a popWindow, a dialoagfragment, or a transparent activity.Copy the code

Summarize some problems and solutions encountered when imitating the main interface of Douyin.

  • The overall technical solution of Douyin is a combination of vertical viewpager+ pull-down refresh + pull-up loading control +fragment. We have a mature open source solution for both the former and the latter, we just combine them. This first step isn’t really that difficult.

  • Use FragmentStatePagerAdapter as far as possible. FragmentPagerAdapter is not recommended. You probably use FragmentPagerAdapter more often than not, but remember that FragmentPagerAdapter does not free memory, and fragments that you can’t see live in memory. For short video schemes like Tiktok that slide almost infinitely, using FragmentPagerAdapter is definitely oom bound. And use FragmentStatePagerAdapter, for fragment is not visible, system is automatically release the memory, the memory will only keep you can see the fragments and 2 fragmnt before and after the see fragments. Of course, this value can be set dynamically, but at least 3 fragments remain.

  • FragmentStatePagerAdapter. NotifyDataSetChanged () failure? Sometimes the notifyDataSetChanged method is called and the interface does not change? In fact for fragmentStatePagerAdapter interface refresh don’t refresh Redraw redrawn GetItemPosition mainly depend on the method of the return value, default is redrawn returns POSITION_UNCHANGED also is not. The interface is redrawn and fragemnt is redrawn only if POSITION_NONE is returned. A lot of people don’t quite understand what that means, so let me briefly describe the situation:

    For example, if we go to the main screen of Tiktok and we return 10 videos, we play the first one by default. This is the first fragment, right? And then at this point we pull down and refresh 10 more data, and what we should play is the first of these new 10 data. So you wait for the interface to return and insert the new 10 pieces of data into the head of our data source array. The notifyDataSetChanged method is then called. If you don’t have to rewrite getItemPosition method, this method returns POSITION_UNCHANGED by default, this is fragmentStatePagerAdapter think I don’t need to redraw the interface. So you keep playing the same old videos. One might ask, why doesn’t this happen if we keep loading more and more?

    For example, loading now is more preloading, so if we return 10 pieces of data on one page, when we go to the fifth piece of data, we may automatically request the next piece of data. So we keep sliding the viewPager back, because position is constantly changing, so there are constantly new fragments coming in. So regardless of how the value of getItemPosition changes, we will refresh the screen in this case.

    However, this is not true for drop-down refresh, because we load the first piece of data by default. We already have this piece of data in memory. For the fragment with position 0, it is already in memory. Even though we called notifyDataSetChanged, we found that the fragment at position 0 was already in the fragment, and getItemPosition returned POSITION_UNCHANGED, so I won’t redraw it. This is a bug prone area.

  • So in that case getItemPosition is fixed and returns POSITION_NONE okay? The answer is no. The POSITION_NONE value is always returned, which can solve the problem of not refreshing the drop-down refresh screen, but can cause new problems. There are mainly 2: First, the fixed return of POSITION_NONE means that every time notifyDataSetChanged is called, the three fragments in our memory have to be redrawn. This cost is too high, low-end phones will obviously get stuck, and Most android video playback is soft decoding scheme. This performance is not good.

    The second: Again, the same preloading, let’s say we return 10 data on the first page, and when we go to the fifth page, we preload the second page and then the second page comes back and we call notifyDataSetChanged, Note that we may not have finished watching the video corresponding to the fifth data at this time, for example, we only saw the sixth second of this short video, but the whole interface was suddenly redrawn and directly started to play from the first second. The experience is clearly unacceptable.

    So what we want to do is return POSITION_NONE when we need it and POSITION_UNCHANGED when we don’t, and the logic can be adjusted for your own business.

    For example, if the id in the source data (mData) is equal to the ID in the fragmetn that is playing, we decide that we don’t need to refresh the screen otherwise it’s not equal, and we swipe it, which corresponds to both loading more and pulling the refresh.

  • How do I locate memory leaks? For the player, if the team is inexperienced for the first time, even with the help of the open source player of SITE B, the problem of memory leakage will occur. For example, when we draw a player interface, we will inevitably draw a progress bar and display the countdown. The default running light effect of TextView is so poor. You may even need to write a custom view to complete the special effects of running lights, which will have to use threads, handlers, timers and so on prone to memory leaks. Therefore, if the fragment is not released in time during continuous sliding, there will definitely be oom problem when it goes online. For Android Studio 3.0 or above:

Well, since Mat can read it, the rest of it won’t be so wordy.

  • How to obtain the fragment based on index? A knowledge point, this also is relatively small for fragmentStatePagerAdapter, we know that in addition to the currently used in fragments, we also have two fragments, before and after the fragments for sliding operation, We have to at least complete the slide to the next fragmetn and stop the previous fragment’s video playing, animation playing, etc. Therefore, it is very important to fetch fragment objects based on index.

Here is an implementation of reflection:

 public static Fragment getIndexFragment(FragmentStatePagerAdapter fragmentStatePagerAdapter, int index) {
        try {
            Field privateArrayList = FragmentStatePagerAdapter.class.getDeclaredField("mFragments");
            privateArrayList.setAccessible(true);
            ArrayList<Fragment> mFragments = (ArrayList<Fragment>) privateArrayList.get(fragmentStatePagerAdapter);
            return mFragments.size() > 0 ? mFragments.get(index) : null;

        } catch (NoSuchFieldException e) {
        } catch (IllegalAccessException e) {
        }
        return null;
    }
Copy the code