0

I wanted to ask if someone of you encountered the same problem as I am.

I/art: Do partial code cache collection, code=250KB, data=130KB
I/art: After code cache collection, code=248KB, data=129KB
I/art: Increasing code cache capacity to 1024KB
I/Choreographer: Skipped 143 frames!  The application may be doing too much work on its main thread.

The design of my Android Application is simple, I have a Navigation Drawer in my landing page then I have Multiple Fragments inside each Drawer Item... So it means that I am using the Activity only at my Landing page where NavDrawer is being used.

When I tried to add a public repository like calendar, recycler views on each of my Fragments I get the error above.

I read some articles and example online and found out that I should use AsyncTask<> or runOnUIThread and run the operations separated from the Main Thread/UI Thread. Eventhough I tried to apply those Threads on my Fragment same error I get.

But the operations is not really heavy, I just loaded the calendar library and instantiate them on my onCreateView inside my Fragment...

I hope you could give me some advice or best practice to manage this kind of scenario... I know someone encountered the same problem. hehe. thanks in advance.

I tried this link, but it is more likely another scenario

AS REQUESTED for the CODES:

public class CalendarFragment extends Fragment implements
        RobotoCalendarView.RobotoCalendarListener,
        CalendarListAdapter.OnItemClickListener
        // CalendarListAdapter.CallbackInterface // Should Implemented on the Main thread/Activity if used as fragment
{

    private RobotoCalendarView robotoCalendarView;
    private Context context;

    private CalendarListAdapter mListAdapter;
    private RecyclerView mSearchResultsList;
    private static final int REQUEST_CODE = 1234;

    private List<ServiceJobWrapper> results = null;


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View view = /*(View)*/ inflater.inflate(
                R.layout.calendar_activity, container, false);
        setContext(container.getContext());

        /**NOTE FROM HERE**/
        setUpCalendarView(view);
//        UICalendarLibTask mCalendarTask = new UICalendarLibTask(view);
//        mCalendarTask.execute((Void) null);

       /* setUpRecyclerView(view);
        setupResultsList(view);
        if (results == null) {
            //final View view = v;
            *//*new Thread(new Runnable() {
                public void run() {
                    populateCardList();
                }
            }).start();*//*
            UITask mAuthTask = new UITask();
            mAuthTask.execute((Void) null);
            // populateCardList();

        }*/
        return view;
    }

    /*@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Log.d("CalendarFragment:",  "I'm on the onCreate");
    }*/
    /**
     * These Two Lines should be included on every Fragment to maintain the state and donnot load again
     *
     * @param outState
     */
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        setRetainInstance(true);
        Log.d("CalendarFragment: ", "I'm on the onSaveInstanceState");
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (results == null) { // If Data is Null then fetch the Data List again
//            UpdateJobServiceTask task = new UpdateJobServiceTask(this.getView());
//            task.execute("");
            //populateCardList();
        } else { // Restore the Data List again
            mListAdapter.swapData(results);
        }
        Log.d("CalendarFragment: ", "I'm on the onActivityCreated");
    }

    private void setContext(Context c) {
        this.context = c;
    }

    public void setUpRecyclerView(View upRecyclerView) {
        mSearchResultsList = (RecyclerView) upRecyclerView.findViewById(R.id.calendar_service_job_list);
    }

    public void setupResultsList(View view) {
        mListAdapter = new CalendarListAdapter(view.getContext());
        mSearchResultsList.setAdapter(mListAdapter);
        mSearchResultsList.setLayoutManager(new LinearLayoutManager(view.getContext()));
    }

    /**
     * Set up the Calendar View Listener on Click of the Date/Month
     *
     * @param view
     */
    private void setUpCalendarView(View view) {
        // Gets the calendar from the view
        robotoCalendarView = (RobotoCalendarView) view.findViewById(R.id.robotoCalendarPicker);
        Button markDayButton = (Button) view.findViewById(R.id.markDayButton);
        markDayButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Calendar calendar = Calendar.getInstance();
                Random random = new Random(System.currentTimeMillis());
                int style = random.nextInt(2);
                int daySelected = random.nextInt(calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
                calendar.set(Calendar.DAY_OF_MONTH, daySelected);

                switch (style) {
                    case 0:
                        robotoCalendarView.markCircleImage1(calendar);
                        break;
                    case 1:
                        robotoCalendarView.markCircleImage2(calendar);
                        break;
                    default:
                        break;
                }
            }
        });

        // Set listener, in this case, the same activity
        robotoCalendarView.setRobotoCalendarListener(this);

        robotoCalendarView.setShortWeekDays(false);

        robotoCalendarView.showDateTitle(true);

         robotoCalendarView.updateView();
    }

//    @Override
//    protected void attachBaseContext(Context newBase) {
//        super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
//    }

    /*@Override
    public void onAttach(Context context) {
        super.onAttach(context);
        //super.onAttach(CalligraphyContextWrapper.wrap(context));
    }*/

    @Override
    public void onDayClick(Calendar daySelectedCalendar) {
        Log.d("onDayClick: ", daySelectedCalendar.getTime() + "");
    }

    @Override
    public void onDayLongClick(Calendar daySelectedCalendar) {
        Log.d("onDayLongClick: ", daySelectedCalendar.getTime() + "");
    }

    @Override
    public void onRightButtonClick() { Log.d("onRightButtonClick!", "Calendar"); }

    @Override
    public void onLeftButtonClick() {
        Log.d("onLeftButtonClick!", "Calendar");
        // Toast.makeText(this.context, "onLeftButtonClick!", Toast.LENGTH_SHORT).show();
    }

    private void activityResultIntent() {
        Intent check = new Intent();
        startActivityForResult(check, REQUEST_CODE);
    }

    /**
     * Setting up for the Result OnClick inside the CardView on the List Adapter
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (resultCode) {

            case RESULT_OK:

                /*if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
                    System.out.println("I'm in onActivityResult");
                    _speaker = new Speaker(getApplicationContext());
                    ImageButton buttonSpeakKoreanAlphabet = (ImageButton) findViewById(R.id.buttonSpeakKorean_alphabet);
                    buttonSpeakKoreanAlphabet.setClickable(true);
                } else {
                    Intent install = new Intent();
                    install.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
                    startActivity(install);
                }*/

                break;

            case RESULT_CANCELED:
                // ... Handle this situation
                break;
            default:
                break;
        }
    }

    private void populateCardList() {
        // Data to be Fetch to the CardView
        // List<ServiceJobWrapper> results = null;//getAllData(this.getContext());
        /*new UIThreadHandler(getContext()).runOnUiThread(new Runnable() {
            @Override
            public void run() {

            }
        });*/
        results = getAllDetailsOfLetters();
        mSearchResultsList.setHasFixedSize(true);
        mSearchResultsList.setLayoutManager(new LinearLayoutManager(context));
        mSearchResultsList.setItemAnimator(new DefaultItemAnimator());
        mListAdapter.swapData(results);

    }

    private class UpdateJobServiceTask extends AsyncTask<String, Void, String> {

        private View mView;

        public UpdateJobServiceTask(View view) {
            mView = view;
        }

        @Override
        protected String doInBackground(String... params) {
            populateCardList();

            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            //textView.setText(result);
        }
    }

    /***********************************
     * TEST                            *
     ***********************************/

    // Getting Details Data of all ALPHABET
    public List<ServiceJobWrapper> getAllDetailsOfLetters() {
        ArrayList<ServiceJobWrapper> translationList = new ArrayList<>();
        int x = 0;
        do {
            ServiceJobWrapper alpha = new ServiceJobWrapper();
            alpha.setID(Integer.parseInt(x + ""));
            alpha.setDay(x + "");
            alpha.setDate("TestDate" + x);
            alpha.setServiceNumber("00" + x);
            alpha.setCustomer("Customer" + x);
            alpha.setEngineer("Engineer" + x);
            alpha.setStatus((x % 2 == 1) ? "Pending" : "Completed");
            translationList.add(alpha);
            x++;
        } while (x != 10);

        return translationList;
    }


    @Override
    public void onClick(ServiceJobWrapper colorWrapper) {

    }

    /**
     * Represents an asynchronous Task
     * UITask mAuthTask = new UITask();
     mAuthTask.execute((Void) null);
     */
    public class UITask extends AsyncTask<Void, Void, Boolean> {
        UITask() {
        }

        @Override
        protected Boolean doInBackground(Void... params) {
            // TODO: attempt authentication against a network service.

            /*try {
                // Simulate network access.
                Thread.sleep(2000);
                // init_DrawerNav();
                //populateCardList();
            } catch (InterruptedException e) {
                return false;
            }*/

            results = getAllDetailsOfLetters();
            // TODO: register the new account here.
            return true;
        }

        @Override
        protected void onPostExecute(final Boolean success) {
            mSearchResultsList.setHasFixedSize(true);
            mSearchResultsList.setLayoutManager(new LinearLayoutManager(context));
            mSearchResultsList.setItemAnimator(new DefaultItemAnimator());
            mListAdapter.swapData(results);
        }

        @Override
        protected void onCancelled() {
        }
    }

    public class UICalendarLibTask extends AsyncTask<Void, Void, Boolean> {
        private View view;
        UICalendarLibTask(View v) {
            this.view = v;
        }

        @Override
        protected Boolean doInBackground(Void... params) {

            return true;
        }

        @Override
        protected void onPostExecute(final Boolean success) {
            setUpCalendarView(view);
        }

        @Override
        protected void onCancelled() {
        }
    }

}

Calling this on the onCreateView same result:

setUpCalendarView(view); // First try without asynTask
// Second try with asynTask
//        UICalendarLibTask mCalendarTask = new UICalendarLibTask(view);
//        mCalendarTask.execute((Void) null);

This is my XML layout for the Fragment:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20sp"
android:background="@drawable/background">


<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/frameLayoutCalendar">

    <com.marcohc.robotocalendar.RobotoCalendarView
        android:id="@+id/robotoCalendarPicker"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</FrameLayout>

<FrameLayout
    android:layout_width="match_parent"
    android:id="@+id/frameLayoutButton"
    android:layout_height="wrap_content">

    <Button
        android:text="TEST RANDOM"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/markDayButton" />
</FrameLayout>

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:isScrollContainer="true"
    android:id="@+id/frameLayoutListOfServices">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/calendar_service_job_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:clipToPadding="false"
        android:paddingTop="60dp" />
</FrameLayout>

Well I don't see any error from my thread especially when populating the cardview, but still, when I tried to render both the recyclerView and the Calendar on the same Fragment, I get the error above

NOTE: I am using this repo from github for the calendar view RobotoCalendar Github

Ric17101
  • 1,063
  • 10
  • 24
  • Show some code, especially your asynchronous operations. Ensure that the reason for the skipped frames isn't something else, for example by leaving out some operations. – aha Feb 23 '17 at 09:19
  • any help from you? Thanks – Ric17101 Feb 24 '17 at 05:09
  • That's a big amount of code. If you reduce it to the relevant sections this would make it easier for people trying to help you but also help you to narrow the reasons for the skipped frames. The UI interaction (calendar set-up) has to happen on the UI thread. You could only leave stuff out if there are actually performance problems. Do you have performance problems or is only the Choreographer complaining? See also http://stackoverflow.com/questions/15963969/choreographer639-skipped-50-frames – aha Feb 24 '17 at 08:32
  • Yes I think this is only performance issues that is correlated with Choreographer... and I think i will just play around using the thread functions. – Ric17101 Feb 24 '17 at 09:47
  • Is there really a problem (i.e. animation stutters on real device) or is just the Choreographer complaining? If it's the latter it's probably not a real problem an can be caused for example by a slow emulator. Besides no amount of threading is going to help when your problem is the manipulation of the UI. You are not allowed to manipulate the UI on a separate thread. – aha Feb 24 '17 at 11:05
  • both is my problem, when I tried to run it on emulator it is slowing down and same thing with the device. The Choreographer always shows off on debug mode. My RAM is 8G, I think there's no.problem.with the emulator, I used Genymotion Tablet Emulator – Ric17101 Feb 24 '17 at 14:38

1 Answers1

1

I don't understand the mystery behind my solution but this resolved my problems...

BEFORE

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="20sp"
    android:background="@drawable/background">

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/frameLayoutCalendar">

<com.marcohc.robotocalendar.RobotoCalendarView
    android:id="@+id/robotoCalendarPicker"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

AFTER (I just removed the line android:background="@drawable/background")

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="20sp">

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
android:id="@+id/frameLayoutCalendar">

<com.marcohc.robotocalendar.RobotoCalendarView
    android:id="@+id/robotoCalendarPicker"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

Will someone explain to me this scenario... Should I really don't need to set the background of my layout, for the sake of not having this Choreagrapher error, thanks!

I hope someone will help this too,

Ric17101
  • 1,063
  • 10
  • 24