doInBackground 方法中的 ArrayIndexOutOfBoundsException

ArrayIndexOutOfBoundsException in doInBackground method

请帮我解决这个错误。即使在 execute() 方法中传递值后,我仍然无法解决此问题。

Caused by: java.lang.ArrayIndexOutOfBoundsException: length=0; index=0 at com.iamsharzil.constraintlayoutproject.DownloadNews.doInBackground(DownloadNews.java:54) at com.iamsharzil.constraintlayoutproject.DownloadNews.doInBackground(DownloadNews.java:22)

DownloadNews.java

String NEWS_SOURCE = "bbc-news";
ArrayList<HashMap<String, String>> dataList = new ArrayList<HashMap<String, String>>();

private Activity mContext;

String API_KEY = "4f5f4fbf57f7476ba41c276b28379a6b";
ListView listNews;

static final String KEY_AUTHOR = "author";
static final String KEY_TITLE = "title";
static final String KEY_DESCRIPTION = "description";
static final String KEY_URL = "url";
static final String KEY_URLTOIMAGE = "urlToImage";
static final String KEY_PUBLISHEDAT = "publishedAt";


public DownloadNews(BaseDrawerActivity mContext) {
    this.mContext = mContext;
    Log.i("Constructor", "Download News called");
}

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

protected String doInBackground(String... args) {

    String xml = "";

       String url = args[0];
        Log.i("URL", url);

        xml = Function.executeGet(url);
        return xml;

}

@Override
protected void onPostExecute(String xml) {

    if(null != xml && xml.length()>10) {
        try {
            JSONObject jsonResponse = new JSONObject(xml);
            JSONArray jsonArray = jsonResponse.optJSONArray("articles");

            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                HashMap<String, String> map = new HashMap<String, String>();
                map.put(KEY_AUTHOR, jsonObject.optString(KEY_AUTHOR).toString());
                map.put(KEY_TITLE, jsonObject.optString(KEY_TITLE).toString());
                map.put(KEY_DESCRIPTION, jsonObject.optString(KEY_DESCRIPTION).toString());
                map.put(KEY_URL, jsonObject.optString(KEY_URL).toString());
                map.put(KEY_URLTOIMAGE, jsonObject.optString(KEY_URLTOIMAGE).toString());
                map.put(KEY_PUBLISHEDAT, jsonObject.optString(KEY_PUBLISHEDAT).toString());
                dataList.add(map);
            }
        } catch (JSONException e) {
            Toast.makeText(mContext, "Unexpected error", Toast.LENGTH_SHORT).show();
        }

        listNews = (ListView) mContext.findViewById(R.id.listNews);
        ListNewsAdapter adapter = new ListNewsAdapter((Activity) mContext, dataList);
        listNews.setAdapter(adapter);

        listNews.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
                Intent i = new Intent(mContext, DetailsActivity.class);
                i.putExtra("url", dataList.get(+position).get(KEY_URL));
                mContext.startActivity(i);
            }
        });


    }else{
        Toast.makeText(mContext, "No news found", Toast.LENGTH_SHORT).show();
    }
}

}

BaseDrawerActivity.java

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

    toolbar.setTitle("NEWS");

    listNews = (ListView) findViewById(R.id.listNews);

    DrawerLayout drawer = (DrawerLayout) 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();

    navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);

    if(Function.isNetworkAvailable(getApplicationContext()))
    {
        DownloadNews newsTask = new DownloadNews(this);
        newsTask.execute();
    }else{
        Toast.makeText(getApplicationContext(), "No Internet Connection", Toast.LENGTH_LONG).show();
    }
}

public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();
    Fragment fragment = null;

    if (id == R.id.nav_general) {
      String general =  "https://newsapi.org/v2/top-headlines?country=in&apiKey=" + API_KEY;
        new DownloadNews(this).execute(general);

    } else if (id == R.id.nav_sports) {
        String sports =  "https://newsapi.org/v2/top-headlines?categoty=sports&country=in&apiKey=" + API_KEY;

        new DownloadNews(this).execute(sports);
    } else if (id == R.id.nav_business) {
        String business =  "https://newsapi.org/v2/top-headlines?categoty=business&country=in&apiKey=" + API_KEY;

        new DownloadNews(this).execute(business);
    } else if (id == R.id.nav_technology) {
        String technology =  "https://newsapi.org/v2/top-headlines?categoty=technology&country=in&apiKey=" + API_KEY;
        new DownloadNews(this).execute(technology);

    } else if (id == R.id.nav_entertainment) {
        String entertainment =  "https://newsapi.org/v2/top-headlines?categoty=entertainment&country=in&apiKey=" + API_KEY;
        new DownloadNews(this).execute(entertainment);

    } else if (id == R.id.nav_health) {
        String health =  "https://newsapi.org/v2/top-headlines?categoty=health&country=in&apiKey=" + API_KEY;
        new DownloadNews(this).execute(health);

    } else if (id == R.id.nav_science) {
        String science =  "https://newsapi.org/v2/top-headlines?categoty=science&country=in&apiKey=" + API_KEY;
        new DownloadNews(this).execute(science);

    }

    if(fragment!=null) {
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.screen_area, fragment);
        ft.commit();
    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}

当用户单击任何我希望更改的菜单项时 url。

Function.java

public class Function {

    public static boolean isNetworkAvailable(Context context) {
        return ((ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE)).
                getActiveNetworkInfo()!=null;
    }

    public static String executeGet(String targetURL) {
        URL url;
        HttpURLConnection connection = null;

        try {
            //Create connection
            url = new URL(targetURL);
            connection = (HttpURLConnection)url.openConnection();

            //connection.setRequestMethod("POST");
            //connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

            connection.setRequestProperty("content-type", "application/json;  charset=utf-8");
            connection.setRequestProperty("Content-Language", "en-US");

            connection.setUseCaches (false);
            connection.setDoInput(true);
            connection.setDoOutput(false);

            InputStream is;

            int status = connection.getResponseCode();

            if (status != HttpURLConnection.HTTP_OK)
                is = connection.getErrorStream();
            else
                is = connection.getInputStream();

            BufferedReader rd = new BufferedReader(new InputStreamReader(is));
            String line;
            StringBuffer response = new StringBuffer();

            while((line = rd.readLine()) != null) {
                response.append(line);
                response.append('\r');
            }
            rd.close();
            return response.toString();
        } catch (Exception e) {
           return null;
        } finally {
            if(connection != null) {
                connection.disconnect();
            }
        }
    }

}

你在这里调用执行:

if(Function.isNetworkAvailable(getApplicationContext()))
{
    DownloadNews newsTask = new DownloadNews(this);
    newsTask.execute(); // <-
}else{
    Toast.makeText(getApplicationContext(), "No Internet Connection", Toast.LENGTH_LONG).show();
}

但不传递参数。这将导致您的方法失败,因为您无法访问零长度数组的第零项。您要么需要确保始终向其传递数据,要么需要执行以下操作:

protected String doInBackground(String... args) {
  String xml = "";

  if (args.length > 0) { 
   String url = args[0];
    Log.i("URL", url);
    xml = Function.executeGet(url);
  }

   return xml;
}

这样,如果 args 为空,您 return 一个空字符串,然后可以在需要的地方处理它。

根据 how to call async task with different url 和@Justin-Pearce 的回答,我能够解决错误。

BaseDrawerActivity.java

public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();
    Fragment fragment = null;

    String general = null, health = null, sports = null, business = null, technology = null, science = null, entertainment = null;

    if (id == R.id.nav_general) {
        general = "https://newsapi.org/v2/top-headlines?country=in&pageSize=100&apiKey=" + API_KEY;

    } else if (id == R.id.nav_sports) {
        sports =  "https://newsapi.org/v2/top-headlines?country=in&category=sports&pageSize=100&apiKey=" + API_KEY;

    } else if (id == R.id.nav_business) {
        business =  "https://newsapi.org/v2/top-headlines?country=in&category=business&pageSize=100&apiKey=" + API_KEY;

    } else if (id == R.id.nav_technology) {
        technology =  "https://newsapi.org/v2/top-headlines?country=in&category=technology&pageSize=100&apiKey=" + API_KEY;

    } else if (id == R.id.nav_entertainment) {
        entertainment =  "https://newsapi.org/v2/top-headlines?country=in&category=entertainment&pageSize=100&apiKey=" + API_KEY;

    } else if (id == R.id.nav_health) {
        health =  "https://newsapi.org/v2/top-headlines?country=in&category=health&pageSize=100&apiKey=" + API_KEY;

    } else if (id == R.id.nav_science) {
        science =  "https://newsapi.org/v2/top-headlines?country=in&category=science&pageSize=100&apiKey=" + API_KEY;

    }

    new DownloadNews(this).execute(
            general,
            sports,
            business,
            technology,
            entertainment,
            health,
            science);

    if(fragment!=null) {
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.screen_area, fragment);
        ft.commit();
    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}

DownloadNews.java

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

protected String doInBackground(String... args) {

    String xml = "";
    for(String urls: args) {
        try {
            String u = new String(urls);
            xml = Function.executeGet(u);
            Log.i("args length", String.valueOf(args.length));
            Log.i("URL", u);

        } catch (Exception e) {}
    }

    return xml;
}