1

I've fixed my last problem with the project (here), but a new one appeared... I'll put needed classes here, so any more or less lazy person can just read stuff from there.


Problem

Step 1. Launch an app
Step 2. Select an item from navigation bar
Step 3 - bug. Data doesn't load, nothing appears.
Step 4. Select any other item from navbar
Step 5. Everything works correctly.

Basically the first time "doesn't work". After step 4, everything is normal until I apply any change or rebuild an app.


Files

MainActivity

public class MainActivity extends AppCompatActivity {

    private DrawerLayout drawer;
    private Handler mHandler;

    private static final String TAG_00 = "home";
    private static final String TAG_01 = "gui_yast";
    private static final String TAG_02 = "gui_network";
    private static final String TAG_03 = "gui_users";
    private static final String TAG_04 = "gui_remote";
    private static final String TAG_05 = "gui_disks";
    private static final String TAG_06 = "gui_install";
    private static final String TAG_07 = "gui_custom";
    private static final String TAG_08 = "gui_gvim";
    private static final String TAG_09 = "cli_fs";
    private static final String TAG_10 = "cli_intro";
    private static final String TAG_11 = "cli_vim";
    private static final String TAG_12 = "cli_remote";
    private static final String TAG_13 = "cli_init";
    private static final String TAG_14 = "cli_process";
    private static final String TAG_15 = "cli_users";
    private static final String TAG_16 = "cli_software";
    private static final String TAG_17 = "cli_admin";
    private static final String TAG_18 = "cli_rescue";
    public static String CURR_TAG = TAG_00;

    private NavigationView navigationView;
    public int navItemIndex = 0;
    private String[] fragmentTitles;
    boolean shouldLoadHomeOnBack = true;
    Fragment fragment;

    Utils u = Utils.getInstance();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        fragmentTitles = getResources().getStringArray(R.array.nav_fragment_titles);
        mHandler = new Handler();
        navigationView = findViewById(R.id.nav_view);

        drawer = findViewById(R.id.drawer_layout);

        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        setUpNavigationView();

        if (savedInstanceState == null) {
            navItemIndex = 0;
            CURR_TAG = TAG_00;
            loadHomeFragment();
        }

    }

    public void loadHomeFragment() {
        selectNavMenu();
        setToolbarTitle();
        if (getSupportFragmentManager().findFragmentByTag(CURR_TAG) != null) {
            drawer.closeDrawers();
            return;
        }
        Log.d("FragmentTransaction","Step before transaction");

        Runnable pendingRunnable = new Runnable() {
            @Override
            public void run() {
                Fragment fragment = getHomeFragment();
                FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
                Log.d("FragmentTransaction","Transaction began");
                fragmentTransaction.replace(R.id.frame_container, fragment, CURR_TAG);
                fragmentTransaction.commitAllowingStateLoss();
                Log.d("FragmentTransaction","Transaction "+CURR_TAG+" is finished");
            }
        };

        mHandler.post(pendingRunnable);
        drawer = findViewById(R.id.drawer_layout);
        drawer.closeDrawers();
        invalidateOptionsMenu();
    }

    private Fragment getHomeFragment() {
        switch (navItemIndex) {
            case 0:
                u.setItemLoaded(0);
                fragment = new HomeFragment();
                return fragment;
            default:
                u.setItemLoaded(navItemIndex);
                new AsyncListLoad(u.getURL(navItemIndex),this).execute();
                fragment = new ContentFragment();
                return fragment;
        }
    }

    private void setToolbarTitle() {
        getSupportActionBar().setTitle(fragmentTitles[navItemIndex]);
    }

    private void selectNavMenu() {
        navigationView.getMenu().getItem(navItemIndex).setChecked(false);
    }

    private void setUpNavigationView() {
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                int id = item.getItemId();
                switch (id) {
                    case R.id.nav_home:
                        navItemIndex = 0;
                        CURR_TAG = TAG_00;
                        break;
                    case R.id.gui_yast:
                        navItemIndex = 1;
                        CURR_TAG = TAG_01;
                        break;
                    case R.id.gui_network:
                        navItemIndex = 2;
                        CURR_TAG = TAG_02;
                        break;
                    case R.id.gui_users:
                        navItemIndex = 3;
                        CURR_TAG = TAG_03;
                        break;
                    // There's 18, so I'll skip them
                }
                loadHomeFragment();

                return true;
            }
        });
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawers();
            return;
        }

        // This code loads home fragment when back key is pressed
        // when user is in other fragment than home
        if (shouldLoadHomeOnBack) {
            // checking if user is on other navigation menu
            // rather than home
            if (navItemIndex != 0) {
                navItemIndex = 0;
                CURR_TAG = TAG_00;
                loadHomeFragment();
                return;
            }
        }

        super.onBackPressed();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

Utils

public class Utils {

    private static final Utils ourInstance = new Utils();

    public static Utils getInstance() {
        return ourInstance;
    }

    private Utils() {
    }

    public ArrayList<String> subURL = new ArrayList<>();

    public String getSubURL(int i) {
        return subURL.get(i);
    }

    public void addSubURL(String subURL, int stringIndex) {
        this.subURL.add(stringIndex,subURL);
    }

    public void clearSubList() {
        subURL.clear();
    }

    public int itemLoaded;
    public int subItemLoaded;
    private ArrayList<DataItem> dataSet = new ArrayList<>();
    private ArrayList<Article> articleSet = new ArrayList<>();

    public void setItemLoaded(int itemLoaded) {
        this.itemLoaded = itemLoaded;
    }

    public int getItemLoaded() {
        return itemLoaded;
    }

    public void setDataSet(ArrayList<DataItem> dataSet) {
        this.dataSet = dataSet;
    }

    public ArrayList<DataItem> getDataSet() {
        return dataSet;
    }

    public ArrayList<Article> getArticleSet() {
        return articleSet;
    }

    public void setArticleSet(ArrayList<Article> articleSet) {
        this.articleSet = articleSet;
    }

    public int getSubItemLoaded() {
        return subItemLoaded;
    }

    public void setSubItemLoaded(int subItemLoaded) {
        this.subItemLoaded = subItemLoaded;
    }

    public String getURL(int itemLoaded) {
        switch (itemLoaded) {
            case 1:
                return "http://susehowto.dx.am/gui/yast";
            case 2:
                return "http://susehowto.dx.am/gui/network";
            case 3:
                return "http://susehowto.dx.am/gui/users";
            case 4:
                return "http://susehowto.dx.am/gui/remote";
            case 5:
                return "http://susehowto.dx.am/gui/disks";
            case 6:
                return "http://susehowto.dx.am/gui/install";
            case 7:
                return "http://susehowto.dx.am/gui/custom";
            case 8:
                return "http://susehowto.dx.am/gui/gvim";
            case 9:
                return "http://susehowto.dx.am/cli/fs";
            case 10:
                return "http://susehowto.dx.am/cli/intro";
            case 11:
                return "http://susehowto.dx.am/cli/vim";
            case 12:
                return "http://susehowto.dx.am/cli/remote";
            case 13:
                return "http://susehowto.dx.am/cli/init";
            case 14:
                return "http://susehowto.dx.am/cli/process";
            case 15:
                return "http://susehowto.dx.am/cli/users";
            case 16:
                return "http://susehowto.dx.am/cli/software";
            case 17:
                return "http://susehowto.dx.am/cli/admin";
            case 18:
                return "http://susehowto.dx.am/cli/rescue";
            default:
                return "";
        }
    }
}

AsyncListLoad

public class AsyncListLoad extends AsyncTask<String,Void,ArrayList<DataItem>> {

    private Activity activity;
    private String target_url;
    private ArrayList<DataItem> dataSet;
    private Utils u = Utils.getInstance();
    private ProgressDialog dialog;

    public AsyncListLoad(String url, Activity activity) {
        this.activity = activity;
        dialog = new ProgressDialog(activity);
        this.target_url = url;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        dialog.setIndeterminate(false);
        dialog.setMessage("Ładowanie zawartości");
        dialog.setCancelable(false);
        dialog.show();
    }

    @Override
    protected ArrayList<DataItem> doInBackground(String... strings) {
        dataSet = new ArrayList<>();
        try {
            Document mSectionDocument = Jsoup.connect(target_url).get();
            Elements mElementSectionSize = mSectionDocument.select("div[class=section]");
            int mElementSize = mElementSectionSize.size();
            u.clearSubList();
            for (int i=0; i < mElementSize; i++) {
                Elements mElementSectionTitle = mSectionDocument.select("span[class=section-name]").select("a").eq(i);
                String mSectionTitle = mElementSectionTitle.text();

                Elements sectionLinks = mSectionDocument.select("span[class=section-name]").select("a").eq(i);
                String sectionLink = sectionLinks.attr("href");
                u.addSubURL(sectionLink,i);

                Elements mElementSectionDesc = mSectionDocument.select("span[class=section-desc]").eq(i);
                String mSectionDesc = mElementSectionDesc.text();
                if(i>9)u.addSubURL(target_url+"/section_"+(i+1),i);
                else u.addSubURL(target_url+"/section_0"+(i+1),i);
                dataSet.add(new DataItem(mSectionTitle,mSectionDesc));
                Log.d("DataItemCreation","Item no. "+i+" added");
                Log.d("DataItemCreation","Link: "+u.getSubURL(i));
                Log.d("DataItemCreation","Item title: "+dataSet.get(i).getTopicTitle());
                Log.d("DataItemCreation","Item description: "+dataSet.get(i).getTopicDesc());
            }
            publishProgress();
        } catch (HttpStatusException h) {
            Toast.makeText(activity,"Network error",Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return dataSet;
    }

    @Override
    protected void onPostExecute(ArrayList<DataItem> arrayList) {
        arrayList = this.dataSet;
        u.setDataSet(arrayList);
        Log.d("DataSetup","DataSet acquired and loaded.");
        dialog.dismiss();
        RecyclerView recyclerView = activity.findViewById(R.id.content_rv);
        ContentAdapter adapter = (ContentAdapter) recyclerView.getAdapter();
        adapter.notifyDataSetChanged();
    }
}

ContentFragment

public class ContentFragment extends Fragment {

    public ContentAdapter adapter;
    Utils u = Utils.getInstance();
    private static final String TAG = "ContentFragment";
    protected ArrayList<DataItem> dataSet;
    protected RecyclerView.LayoutManager lm;
    protected RecyclerView recyclerView;

    public ContentFragment() {
        //empty public constructor
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initData();
        adapter = new ContentAdapter(dataSet, getActivity());
        lm = new LinearLayoutManager(getActivity());
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable final ViewGroup container, Bundle savedInstanceState) {
        final View v = inflater.inflate(R.layout.content_fragment,container,false);
        v.setTag(TAG);
        recyclerView = v.findViewById(R.id.content_rv);
        setCustomAdapter(recyclerView, lm, adapter);
        final SwipeRefreshLayout rLayout = v.findViewById(R.id.content_swipe);

        rLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                rLayout.setRefreshing(true);
                Toast.makeText(getActivity(),"Refreshed!",Toast.LENGTH_SHORT).show();
                rLayout.setRefreshing(false);
            }
        });
        return v;
    }

    private void initData() {
        dataSet = u.getDataSet();
    }

    public void setCustomAdapter(RecyclerView recyclerView, RecyclerView.LayoutManager layoutManager, ContentAdapter adapter) {
        recyclerView.removeAllViews();
        Log.d("Fragment","RecyclerView added");
        recyclerView.setLayoutManager(layoutManager);
        Log.d("Fragment","LayoutManager is set");
        recyclerView.setAdapter(adapter);
        Log.d("Fragment","Adapter is set");
        adapter.notifyDataSetChanged();
    }
}

ContentAdapter

public class ContentAdapter extends RecyclerView.Adapter<ContentAdapter.ContentViewHolder> {

    private ArrayList<DataItem> dataSet;
    Utils u = Utils.getInstance();
    private Context context;

    public ContentAdapter(ArrayList<DataItem> itemSet, Context context) {
        this.context = context;
        this.dataSet = itemSet;
    }

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

    @NonNull
    @Override
    public ContentAdapter.ContentViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.data_item,parent,false);
        final ContentViewHolder vHolder = new ContentViewHolder(v);
        vHolder.itemLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("SubItemClick","Item "+vHolder.getAdapterPosition()+" is clicked!");
                u.setSubItemLoaded(vHolder.getAdapterPosition());
                Intent run = new Intent(context,DynamicActivity.class);
                Bundle fragData = new Bundle();
                fragData.clear();
                fragData.putString("link",u.getSubURL(vHolder.getAdapterPosition()));
                fragData.putInt("ClickedID",vHolder.getAdapterPosition());
                run.putExtras(fragData);
                context.startActivity(run);
            }
        });
        return vHolder;
    }

    @Override
    public void onBindViewHolder(@NonNull ContentViewHolder holder, int position) {
        holder.topicTitle.setText(dataSet.get(position).getTopicTitle());
        holder.topicDesc.setText(dataSet.get(position).getTopicDesc());
        Log.d("ViewHolderSetup","ViewHolder is bind");
    }

    @Override
    public int getItemCount() {
        return dataSet.size();
    }

    public static class ContentViewHolder extends RecyclerView.ViewHolder {

        public CardView itemLayout;
        public TextView topicTitle;
        public TextView topicDesc;
        public ContentViewHolder(View itemView) {
            super(itemView);
            itemLayout = itemView.findViewById(R.id.dataitem_container);
            topicTitle = itemView.findViewById(R.id.topic_title);
            topicDesc = itemView.findViewById(R.id.topic_desc);
        }
    }
}


Any published data here will be public anyway. Thanks in advance for any help!
C0nverter
  • 114
  • 13
  • 1
    Because data is not loaded yet . `dataSet = u.getDataSet();` will return empty list for first time . Cause `new AsyncListLoad(u.getURL(navItemIndex),this).execute();` is an Asynchronous call so it will update the data later after `doInBackground()`. – ADM Jul 01 '18 at 14:57
  • So what should I do to make sure that the dataset from `AsyncListLoad` is created and not empty? – C0nverter Jul 01 '18 at 15:21
  • 2
    Just load the data inside `Fragment` and provide a callback to Fragment for data loaded. – ADM Jul 01 '18 at 15:40
  • 1
    Could you post it as an answer, so I'll be able to +1 an make as a solution? It solved my 4 day long mind-blowing... – C0nverter Jul 01 '18 at 17:37

1 Answers1

1

Solution provided by @ADM (comments under the question): after data load, callback needs to be provided, so app is able to populate already loaded content.

Essentially, I've created an interface called OnDataLoadListener and put a onDataLoadListener void (notice case-sensitivity, it's important for creation of such interfaces) inside. Then, when data is loaded, I call this void inside ContentAdapter to populate data.

Dharman
  • 30,962
  • 25
  • 85
  • 135
C0nverter
  • 114
  • 13