0

I have made an app where there is a main activity having a navigation drawer. In one of the fragments( i.e SourceFragment), I have made a tabview on top, and a view pager below the tabs, where 2 fragments(i.e AllSourcesFragment and PreferredSourcesFragment) are inflated. I am able to set a spinner in the AllSourcesFragment and impliment it. But I want to set a recyclerView(with cards) below the spinner card. I am able to set the layoutInflater for the recyclerView, i.e when I comment out line a in AllSourcesFragment.java, the app works smoothly with all components working. But when I impliment line a, the following error occours

04-13 15:22:22.171 2662-2662/? E/WindowManager: android.view.WindowLeaked: Activity com.example.kartik.bulletin.MainActivity has leaked window DecorView@bbc06ec[Please wait] that was originally added here at android.view.ViewRootImpl.(ViewRootImpl.java:424) at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:331) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93) at android.app.Dialog.show(Dialog.java:316) at com.example.kartik.bulletin.Downloader.onPreExecute(Downloader.java:49) at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:613) at android.os.AsyncTask.execute(AsyncTask.java:560) at com.example.kartik.bulletin.AllSourcesFragment.onCreateView(AllSourcesFragment.java:42) at android.support.v4.app.Fragment.performCreateView(Fragment.java:2192) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1299) at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595) at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:758) at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2363) at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2149) at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2103) at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:1984) at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:626) at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:143) at android.support.v4.view.ViewPager.populate(ViewPager.java:1268) at android.support.v4.view.ViewPager.populate(ViewPager.java:1116) at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1642) at android.view.View.measure(View.java:19756) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6124) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464) at android.widget.LinearLayout.measureVertical(LinearLayout.java:758) at android.widget.LinearLayout.onMeasure(LinearLayout.java:640) at android.view.View.measure(View.java:19756) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6124) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at android.view.View.measure(View.java:19756) at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:1081) at android.view.View.measure(View.java:19756) at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715) at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461) at android.view.View.measure(View.java:19756) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6124) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:139) at android.view.View.measure(View.java:19756) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6124) at android.support.v7.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:393) at android.view.View.measure(View.java:19756) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6124) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at android.view.View.measure(View.java:19756) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6124) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464) at android.widget.LinearLayout.measureVertical(LinearLayout.java:758) at android.widget.LinearLayout.onMeasure(LinearLayout.java:640) at android.view.View.measure(View.java:19756) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6124) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at com.android.internal.policy.DecorView.onMeasure(DecorView.java:687) 04-13 15:22:22.171 2662-2662/? E/WindowManager: at android.view.View.measure(View.java:19756) at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2283) at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1370) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1619) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1258) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6348) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:871) at android.view.Choreographer.doCallbacks(Choreographer.java:683) at android.view.Choreographer.doFrame(Choreographer.java:619) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6123) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)

AllSourcesFragment.java

package com.example.kartik.bulletin;


import android.content.Context;
import android.os.Bundle;
import android.os.RecoverySystem;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Spinner;

public class AllSourcesFragment extends Fragment {


    Spinner categorySpinner;
    String url = "https://newsapi.org/v1/sources";

    public AllSourcesFragment() {
        // Required empty public constructor
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_all_sources, container, false);



        categorySpinner = (Spinner)view.findViewById(R.id.source_categoryspinner);
        final String[] categories = new String[] { "All categories", "general", "business", "entertainment", "gaming", "music", "science-and-nature", "sport", "technology"};
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item, categories);
        categorySpinner.setAdapter(arrayAdapter);


        RecyclerView recyclerView = (RecyclerView)view.findViewById(R.id.source_recyclerview);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

//Line a that is creating problem 
        new Downloader(getContext(), url, recyclerView, 0, "All Sources").execute();

        return  view;
    }

}

Downloader.java

package com.example.kartik.bulletin;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.widget.Toast;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;

/**
 * Created by kartik on 13/4/17.
 */

public class Downloader extends AsyncTask<Void, Void, String> {



    Context c;
    String jsonUrl, category;
    RecyclerView rv;
    int choice;

    String TAG = "Bla bla";
    ProgressDialog pd;

    public Downloader(Context c, String jsonUrl, RecyclerView rv, int choice, String category) {
        this.c = c;
        this.jsonUrl = jsonUrl;
        this.rv = rv;
        this.choice = choice;
        this.category = category;
    }


    @Override
    protected void onPreExecute() {
        super.onPreExecute();

        pd = new ProgressDialog(c);
        pd.setTitle("Please wait...");
        pd.setMessage("Loading list of news sources");
        pd.show();
    }


    @Override
    protected String doInBackground(Void... params) {
        return download();
    }

    @Override
    protected void onPostExecute(String jsonData) {
        super.onPostExecute(jsonData);

        pd.dismiss();
        if(jsonData.startsWith("Error")){
            String error = jsonData;
            Toast.makeText(c, error, Toast.LENGTH_SHORT).show();
        }else {
            //parser
            if(choice == 0)
                new SourceParser(c, jsonData, rv, category).execute();
            /*else
                new NewsParser(c, jsonData, rv).execute();*/
        }
    }

    private String download(){
        Object connection = Connector.connect(jsonUrl);
        if(connection.toString().startsWith("Error"))
            return connection.toString();

        try{
            HttpURLConnection con = (HttpURLConnection)connection;
            if(con.getResponseCode()==con.HTTP_OK){
                InputStream is = new BufferedInputStream(con.getInputStream());
                BufferedReader br = new BufferedReader(new InputStreamReader(is));

                String line;
                StringBuffer jsonData = new StringBuffer();

                while((line = br.readLine())!=null)
                    jsonData.append(line+"\n");

                br.close();
                is.close();

                Log.d(TAG, jsonData.toString());
                return jsonData.toString();

            }else {
                return "Error" + con.getResponseMessage();
            }
        } catch (IOException e) {
            e.printStackTrace();
            return "Error : "+e.getMessage();
        }
    }
}

SourceParser.java

package com.example.kartik.bulletin;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.widget.Toast;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;

/**
 * Created by kartik on 13/4/17.
 */

public class SourceParser extends AsyncTask<Void, Void, Boolean> {

    Context c;
    String jsonData, category;
    RecyclerView rv;
    String TAG = "NOT bla bla";
    SourceAdapter adapter;

    ProgressDialog pd;
    ArrayList<SourceItem> sourceItems= new ArrayList<>();

    public SourceParser(Context c, String jsonData, RecyclerView rv, String category) {
        this.c = c;
        this.jsonData = jsonData;
        this.rv = rv;
        this.category = category;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        Log.d(TAG, "onPreExecute: parser reached");

        pd = new ProgressDialog(c);
        pd.setTitle("Please wait...");
        pd.setMessage("Loading list of news sourceItems");
        pd.show();
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        Log.d(TAG, "doInBackground: parser reached");
        return parse();
    }

    @Override
    protected void onPostExecute(Boolean isParsed) {
        super.onPostExecute(isParsed);
        Log.d(TAG, "onPosExecute: parser reached");
        pd.dismiss();

        if(isParsed){
            adapter = new SourceAdapter(c, sourceItems);
            rv.setAdapter(adapter);
        }else
            Toast.makeText(c, "Unable to parse", Toast.LENGTH_LONG).show();


    }


    private boolean parse(){
        try{
            sourceItems.clear();
            JSONObject obj = new JSONObject(jsonData);
            JSONArray jsonArray = obj.getJSONArray("sources");
            for(int i=0; i<jsonArray.length(); i++){

                JSONObject jsonObject = (JSONObject) jsonArray.get(i);

                if(!category.equals("All categories") && !category.equals(jsonObject.getString("category")))
                    continue;


                Log.d(TAG, jsonObject.getString("name"));

                String id = jsonObject.getString("id");
                String name = jsonObject.getString("name");
                String description = jsonObject.getString("description");
                String actualUrl= jsonObject.getString("url");
                String category= jsonObject.getString("category");
                String language= jsonObject.getString("language");
                String country= jsonObject.getString("country");

                Log.d(TAG, jsonObject.getString("id"));
                JSONObject urls = jsonObject.getJSONObject("urlsToLogos");

                String surl= urls.getString("small");
                String murl= urls.getString("medium");
                String lurl= urls.getString("large");

                sourceItems.add(new SourceItem(id, name, description, actualUrl, category, language, country, surl, murl, lurl));

                String a = Integer.toString(sourceItems.size());
                Log.d(TAG, a);


            }


            return true;
        } catch (JSONException e) {
            e.printStackTrace();
            return false;
        }
    }
}

SourceAdapter.java

package com.example.kartik.bulletin;

import android.content.Context;
import android.content.Intent;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;

import java.util.List;

/**
 * Created by kartik on 13/4/17.
 */

public class SourceAdapter extends RecyclerView.Adapter<SourceAdapter.SourceViewHolder> {


    private List<SourceItem> sources;
    private Context context;
    private LayoutInflater inflater;


    public SourceAdapter(Context context, List<SourceItem> sources) {
        this.sources = sources;
        this.context = context;
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    public class SourceViewHolder extends RecyclerView.ViewHolder {

        ImageView imageView;
        TextView title, description, category;
        ProgressBar progressBar;
        CardView cardView;
        public SourceViewHolder(View itemView) {
            super(itemView);


            imageView = (ImageView)itemView.findViewById(R.id.source_imageview);
            title = (TextView)itemView.findViewById(R.id.source_title);
            description = (TextView)itemView.findViewById(R.id.source_description);
            category = (TextView)itemView.findViewById(R.id.source_category);
            progressBar = (ProgressBar)itemView.findViewById(R.id.source_progressbar);
            cardView = (CardView)itemView.findViewById(R.id.source_card);


        }

    }





    @Override
    public SourceViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {


        View rootView = inflater.inflate(R.layout.card_source, parent, false);
        return new SourceViewHolder(rootView);
    }

    @Override
    public void onBindViewHolder(final SourceViewHolder holder, int position) {
        final SourceItem item = sources.get(position);

        String cat = "Category : "+item.getCategory();
        holder.title.setText(item.getName());
        holder.description.setText(item.getDescription());
        holder.category.setText(cat);

        Glide.with(context)
                .load(item.getLargeLogoUrl())
                .listener(new RequestListener<String, GlideDrawable>() {
                    @Override
                    public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
                        holder.progressBar.setVisibility(View.GONE);
                        return false;
                    }

                    @Override
                    public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                        holder.progressBar.setVisibility(View.GONE);
                        return false;
                    }
                })
                //.error(R.drawable.image_not_found)
                .into(holder.imageView);


        holder.cardView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                clicked(item);
            }
        });
    }

    private void clicked(SourceItem item) {
        Toast.makeText(context, "Click on any article to read it!", Toast.LENGTH_LONG).show();
        /*Intent intent = new Intent(context, NewsActivity.class);
        intent.putExtra("id", item.getId());
        intent.putExtra("name", item.getName());
        context.startActivity(intent);*/
    }

    @Override
    public int getItemCount() {
        if(sources == null)
            return 0;
        return sources.size();
    }


}

SourceFragment.java

package com.example.kartik.bulletin;

import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class SourceFragment extends Fragment {
    public  static TabLayout tabLayout;
    public  static ViewPager viewPager;
    public  static int int_items= 2;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view =  inflater.inflate(R.layout.fragment_source, null);

        tabLayout=(TabLayout)view.findViewById(R.id.tabs);
        viewPager=(ViewPager)view.findViewById(R.id.viewpager);
        //set an adpater


        viewPager.setAdapter(new MyAdapter(getChildFragmentManager()))  ;

        tabLayout.post(new Runnable() {
            @Override
            public void run() {
                tabLayout.setupWithViewPager(viewPager);
            }
        });

        return view;
    }
}

MainActivity.java

package com.example.kartik.bulletin;

import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity {

    DrawerLayout drawerLayout;
    NavigationView navigationView;
    FragmentManager FM;
    FragmentTransaction FT;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
        navigationView= (NavigationView) findViewById(R.id.shitstuff);

        FM= getSupportFragmentManager();
        FT= FM.beginTransaction();
        FT.replace(R.id.containerView, new SourceFragment()).commit();

        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                drawerLayout.closeDrawers();

                if (item.getItemId()== R.id.nav_articles) {
                    FragmentTransaction fragmentTransaction= FM.beginTransaction();
                    fragmentTransaction.replace(R.id.containerView, new ArticleFragment()).commit();
                }
                if(item.getItemId()==R.id.nav_sources){
                    FragmentTransaction fragmentTransaction1=FM.beginTransaction();
                    fragmentTransaction1.replace(R.id.containerView,new SourceFragment()).commit();
                }
                if(item.getItemId()==R.id.nav_bookmarks){
                    FragmentTransaction fragmentTransaction1=FM.beginTransaction();
                    fragmentTransaction1.replace(R.id.containerView,new BookmarkFragment()).commit();
                }
                return false;
            }
        });


        android.support.v7.widget.Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
        ActionBarDrawerToggle toggle= new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.app_name,R.string.app_name);
        drawerLayout.addDrawerListener(toggle);
        toggle.syncState();
    }
}

I have not shown the other classes, but I have used the same layouts in a seperate project and that app works perfectly(In that app, I have simply put one activity, and one fragment it impliments > AllSourcesFragment. I am new to android and was not able to do good research on this topic. Where am I going wrong?

Kartik Sharma
  • 111
  • 1
  • 1
  • 4

1 Answers1

0

That error generally means that a dialog was left open at the moment that an activity is destroyed.

Either

a) your fragment is actually being destroyed before the asynchronously operating Downloader calls dismiss() on the ProgressDialog in PostExecute or

b) an unrelated error (probably in the download() call in your doInBackground) is causing PostExecute never to be called.

In the latter case you should see the underlying error a bit earlier on in your log file.

See also this question.

Community
  • 1
  • 1
GertG
  • 959
  • 1
  • 8
  • 21