I am trying to make a news app, data obtained from RSS feed. I get xml response from the feed. And I am using XmlPullParser to parse the xml. The parsing is a success. I can see the values in my log.
But somehow I am not able to fill them in my recyclerView. It's all just blank. My java class is:
public class RssNewsActivity extends AppCompatActivity {
private static final String TAG = RssNewsActivity.class.toString();
RssFeedAdapter adapter;
RecyclerView recyclerView_rssFeed;
SwipeRefreshLayout swipeRefreshLayout;
private List<RssModel> listResponseModel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rss_news);
initialize();
recyclerView_rssFeed.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView_rssFeed.setLayoutManager(linearLayoutManager);
adapter = new RssFeedAdapter(RssNewsActivity.this, listResponseModel);
recyclerView_rssFeed.setAdapter(adapter);
fetchNewsFeed();
//if user swipes the recycler then refresh content page
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
fetchNewsFeed();
}
});
}
private void initialize() {
swipeRefreshLayout = findViewById(R.id.swipeRefresh_rssFeed);
recyclerView_rssFeed = findViewById(R.id.recyclerView_rssFeed);
listResponseModel = new ArrayList<>();
}
private void fetchNewsFeed() {
String url = "here is my news feed url";
StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
listResponseModel.clear();
try {
listResponseModel = parseNewsFeed(response);
} catch (XmlPullParserException | IOException e) {
Log.e(TAG, e.getMessage());
}
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
RequestQueue queue = Volley.newRequestQueue(this);
queue.add(request);
}
private List<RssModel> parseNewsFeed(String response) throws XmlPullParserException,
IOException {
XmlPullParserFactory parserFactory = XmlPullParserFactory.newInstance();
parserFactory.setNamespaceAware(true);
XmlPullParser xmlPullParser = parserFactory.newPullParser();
xmlPullParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
xmlPullParser.setInput(new StringReader(response));
return processParsing(xmlPullParser);
}
private List<RssModel> processParsing(XmlPullParser xmlPullParser) throws IOException, XmlPullParserException {
List<RssModel> listRssFeed = new ArrayList<>();
int eventType = xmlPullParser.getEventType();
RssModel rssModel = null;
xmlPullParser.nextTag();
while (eventType != XmlPullParser.END_DOCUMENT) {
String eltName;
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
break;
case XmlPullParser.START_TAG:
eltName = xmlPullParser.getName();
if ("item".equals(eltName)) {
rssModel = new RssModel();
} else if (rssModel != null) {
if ("title".equals(eltName)) {
String title = xmlPullParser.nextText();
rssModel.setTitle(title);
Log.d(TAG, "title: " + title);
} else if ("link".equals(eltName)) {
String link = xmlPullParser.nextText();
rssModel.setLink(link);
Log.d(TAG, "link: " + link);
}
}
break;
case XmlPullParser.END_TAG:
eltName = xmlPullParser.getName();
if ("item".equals(eltName) && rssModel != null) {
listRssFeed.add(rssModel);
}
break;
}
eventType = xmlPullParser.next();
}
return listRssFeed;
}
}
my xml design is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="rssnewsfeed.RssNewsActivity">
<android.support.v4.widget.SwipeRefreshLayout
android:id="#+id/swipeRefresh_rssFeed"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView_rssFeed"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
</RelativeLayout>
This is my adapter class
public class RssFeedAdapter extends RecyclerView.Adapter<RssFeedAdapter.RssViewHolder> {
private Context mContext;
private List<RssModel> mRssFeeds;
public RssFeedAdapter(Context mContext, List<RssModel> mRssFeeds) {
this.mContext = mContext;
this.mRssFeeds = mRssFeeds;
}
#NonNull
#Override
public RssViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(mContext).inflate(R.layout.rss_feed_layout, viewGroup, false);
return new RssViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull RssViewHolder rssViewHolder, int i) {
RssModel post = mRssFeeds.get(i);
rssViewHolder.textView_title.setText(post.getTitle());
rssViewHolder.textView_link.setText(post.getLink());
}
#Override
public int getItemCount() {
return mRssFeeds.size();
}
public class RssViewHolder extends RecyclerView.ViewHolder {
private TextView textView_title, textView_link;
public RssViewHolder(#NonNull View itemView) {
super(itemView);
textView_title = itemView.findViewById(R.id.textView_title);
textView_link = itemView.findViewById(R.id.textView_link);
}
}
}
And finally this is my model class:
public class RssModel {
private String title;
private String link;
public RssModel() {
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
}
I tried many ways but no success. I don't know what I am missing. I will be grateful for any guidance. Thanks.
Giving " = " will create a new instance of ArrayList apart from which is already binded to RecyclerView adapter.
So, you need to change this,
listResponseModel = parseNewsFeed(response);
to
listResponseModel.addAll(parseNewsFeed(response));
This happens because the Rss list which you're passing to recycler view adapter is null as you mentioned earlier you're successfully getting the values in log so another guaranteed workaround is to set the values into an separate arraylist.
So inside your class simply create arraylist:
private ArrayList<String> title;
private ArrayList<String> post;
This will be your initialize method:
private void initialize()
{
swipeRefreshLayout = findViewById(R.id.swipeRefresh_rssFeed);
recyclerView_rssFeed = findViewById(R.id.recyclerView_rssFeed);
title = new ArrayList<>();
post = new ArrayList<>();
}
Now simply pass your values to arraylist:
title.add(title)
post.add(post)
Now pass those arraylist to adapter:
adapter = new RssFeedAdapter(RssNewsActivity.this, title,post);
recyclerView_rssFeed.setAdapter(adapter);
After this initialize arraylist in adapter and fetch your values!
One more Important thing inside your oncreate() place your fetchNewsFeed(); method before initializing the adapter
initialize();
fetchNewsFeed();
recyclerView_rssFeed.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
recyclerView_rssFeed.setLayoutManager(linearLayoutManager);
adapter = new RssFeedAdapter(RssNewsActivity.this, listResponseModel);
recyclerView_rssFeed.setAdapter(adapter);
I implemented EditText widget to filter items in ListFragment using custom ArrayAdapter.
It works fine but the filtered list contains EMPTY items as well as filtered items.
I found that i should clear the adapter before to repopulate it, right?
Could it be something like
adapter.clear();
listview.getAdapter().notifyDataSetChanged();
Anyway I cannot find working solution.
Any clue to fix this bug, please?
public class CustomListAdapter extends ArrayAdapter<UnitView> {
private static final String TAG = "FRAGMENT TWO";
private final Activity context;
private final UnitView[] dataSource;
private UnitView[] unitViews;
public CustomListAdapter(Activity context, UnitView[] units) {
super(context, R.layout.unit, units);
this.context = context;
this.unitViews = units;
this.dataSource = units;
}
public View getView(int position,View view,ViewGroup parent) {
view = null;
try
{
if (view == null)
{
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.listview_item, null);
UnitView uv = unitViews[position];
view.setTag(uv);
TextView textViewTypeName = (TextView) view.findViewById(R.id.textViewTypeName);
textViewTypeName.setText(uv.getDeviceTypeName());
// Code to populate widgets ....
}
}
catch (Exception ex)
{
Log.d(TAG, ex.getMessage());
}
return view;
};
// Filter input data in ListFragment
public void filter(String charText) {
try
{
charText = charText.toLowerCase(Locale.getDefault());
unitViews = new UnitView[dataSource.length];
if (charText.length() == 0) {
unitViews = Arrays.copyOf(this.dataSource, this.dataSource.length);
}
else
{
List<UnitView> result = new ArrayList<UnitView>();
for (UnitView uv : dataSource)
{
if (uv.getNumber().toLowerCase(Locale.getDefault()).contains(charText))
{
result.add(uv);
}
}
if(result.size() > 0)
{
unitViews = result.toArray(new UnitView[result.size()]);
}
}
notifyDataSetChanged();
}
catch (Exception ex)
{
Log.d(TAG, ex.getMessage());
}
}
public static boolean isBlank(String value) {
return (value == null || value.equals("") || value.equals("null") || value.trim().equals(""));
}
}
FragmentTwo.java
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
Gson gson = new Gson();
unitViews = gson.fromJson(s, UnitView[].class);
if (unitViews.length > 0) {
ArrayList<String> names = new ArrayList<String>();
for (int i = 0; i < unitViews.length; i++) {
String name = unitViews[i].getName();
names.add(name);
}
String[] values = names.toArray(new String[unitViews.length]);
adapter = new CustomListAdapter(getActivity(), unitViews);
setListAdapter(adapter);
// Locate the EditText in listview_main.xml
editSearch = (EditText)getActivity().findViewById(R.id.editSearch);
// Capture Text in EditText
editSearch.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
String text = editSearch.getText().toString().toLowerCase(Locale.getDefault());
adapter.filter(text);
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
});
Log.d(TAG, s);
}
}
catch (Exception ex)
{
Log.e(TAG, "Error: ", ex);
}
}
Ok, I found solution by relocating filter code to onPostExecute and re-initializing adapter.
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
Gson gson = new Gson();
unitViews = gson.fromJson(s, UnitView[].class);
if (unitViews.length > 0) {
ArrayList<String> names = new ArrayList<String>();
for (int i = 0; i < unitViews.length; i++) {
String name = unitViews[i].getName();
names.add(name);
}
String[] values = names.toArray(new String[unitViews.length]);
adapter = new CustomListAdapter(getActivity(), unitViews);
setListAdapter(adapter);
// Locate the EditText in listview_main.xml
editSearch = (EditText)getActivity().findViewById(R.id.editSearch);
// Capture Text in EditText
editSearch.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
String text = editSearch.getText().toString().toLowerCase(Locale.getDefault());
// adapter.filter(text);
try
{
text = text.toLowerCase(Locale.getDefault());
UnitView[] resultUnitViews = new UnitView[0];
if (text.length() == 0) {
resultUnitViews = Arrays.copyOf(unitViews, unitViews.length);
}
else
{
List<UnitView> result = new ArrayList<UnitView>();
for (UnitView uv : unitViews)
{
if (uv.getNumber().toLowerCase(Locale.getDefault()).contains(text))
{
result.add(uv);
}
}
if(result.size() > 0)
{
resultUnitViews = result.toArray(new UnitView[result.size()]);
adapter = new CustomListAdapter(getActivity(), resultUnitViews);
setListAdapter(adapter);
}
}
}
catch (Exception ex)
{
Log.d(TAG, ex.getMessage());
}
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
});
Log.d(TAG, s);
}
}
catch (Exception ex)
{
Log.e(TAG, "Error: ", ex);
}
}
I am building an app for Udacity called popular movies app which will fetch movies info from movieDB and display posters in the first activity than if the user clicked any poster it will take him to detailActivity where all the Movie detail will be displayed.
Now I am done with stage 1, stage 2 I am supposed to give the user the ability to make a favorite movie list which will be displayed in the first activity and deatilActivity and will be fetched from and to a database.
I already created the database and I have data saved there but I do not no how to retrieve it and display it to user kindly help me to do it.
below is my code:
First Activity the gridView for posters:
public class PhotoGrid extends Fragment {
//Create a string array variable for every item that we are going to recive from
// the movieDB
String[] movieId, movieTitle, movieReleaseDate, movieVoteAverage, movieOverview, moviePosterPath;
//use string1 to attach the poster path for every poster with the url so we can call the image
static String[] string1;
// define gridView here so we can use it in onPostexecute()
GridView gridView;
//movieUrl is used for the sortby setting
String movieUrl;
SQLiteDatabase db;
databaseHelper databaseHelper;
Cursor cursor;
ContentProvider contentProvider;
public PhotoGrid() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add this line in order for this fragment to handle menu events.
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_refresh) {
updateMovie();
return true;
} else if (id == R.id.action_settings) {
//if action_setting clicked SettingActivity will start
Intent intent = new Intent(getActivity(), SettingActivity.class);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
public void updateMovie() {
FetchMoviesPosters movieTask = new FetchMoviesPosters();
//make popularity as the default order or call for movieposters in settings
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(getActivity());
String sortBy = sharedPreferences.getString(getString(R.string.pref_sortby_key),
getString(R.string.pref_sortby_default));
movieTask.execute(sortBy);
}
#Override
public void onStart() {
super.onStart();
//update movies list on start
updateMovie();
}
#Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_photo_grid, container, false);
databaseHelper = new databaseHelper(getActivity(),MovieContract.MovieEntry.TABLE_NAME,null,2);
db = databaseHelper.getReadableDatabase();
gridView = (GridView) rootView.findViewById(R.id.grid_view);
updateMovie();
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
//Here handle the on poster click action by assigning the clicked poster info
//to strings and send them to detail activity with different keys to be able to
// control each item alone
String movieIDText = movieId[i];
String movieTitleText = movieTitle[i];
String movieOverViewText = movieOverview[i];
String movieReleaseDateText = movieReleaseDate[i];
String movieRatingText = movieVoteAverage[i];
String movieDetailImage = moviePosterPath[i];
Intent intent = new Intent(getActivity(), DetailActivity.class);
intent.putExtra("movie_id", movieIDText);
intent.putExtra("movie_overview", movieOverViewText);
intent.putExtra("movie_title", movieTitleText);
intent.putExtra("movie_release_date", movieReleaseDateText);
intent.putExtra("movie_rating", movieRatingText);
intent.putExtra("image_path", movieDetailImage);
startActivity(intent);
}
});
return rootView;
}
//ImageAdapter is used to control images dimensions and load them in the
// imageview using Picasso
public class ImageAdapter extends BaseAdapter {
private Context mContext;
private String[] mThumbIds;
public ImageAdapter(Context c, String[] str2) {
mContext = c;
mThumbIds = str2;
}
#Override
public int getCount() {
if (mThumbIds != null) {
return mThumbIds.length;
} else {
return 0;
}
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView;
if (convertView == null) {
// if it's not recycled, initialize some attributes
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(700, 1200));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setPadding(4, 4, 4, 4);
} else {
imageView = (ImageView) convertView;
}
Picasso.with(mContext).load(mThumbIds[position]).into(imageView);
return imageView;
}
}
public class FetchMoviesPosters extends AsyncTask<String, Void, String[]> {
private final String LOG_TAG = FetchMoviesPosters.class.getSimpleName();
//in this function the different order settings are defined
private String setOrder(String sortBy) {
if (sortBy.equals(getString(R.string.pref_sorting_popularity))) {
movieUrl = "https://api.themoviedb.org/3/movie/popular?";
} else if (sortBy.equals(getString(R.string.pref_sorting_highest_rating))) {
movieUrl = "https://api.themoviedb.org/3/movie/top_rated?";
}
else if (sortBy.equals(getString(R.string.pref_sorting_favorite))){
cursor = databaseHelper.retrieveData(db);
if (cursor.moveToFirst()){
do {
String id, title, overView, releaseDate, rating, posterPath;
id = cursor.getString(0);
title = cursor.getString(1);
overView = cursor.getString(2);
releaseDate = cursor.getString(3);
rating = cursor.getString(4);
posterPath = cursor.getString(5);
contentProvider = new ContentProvider(id , title , overView
, releaseDate, rating , posterPath);
}while (cursor.moveToNext());
}
}
return sortBy;
}
private String[] MoviesJasonPrase(String moviesPosterStr ) throws JSONException {
final String M_Result = "results";
final String M_ID = "id";
final String M_Title = "original_title";
final String M_Release = "release_date";
final String M_Vote = "vote_average";
final String M_OverV = "overview";
final String M_Poster = "poster_path";
JSONObject moviesJson = new JSONObject(moviesPosterStr);
JSONArray resultsArray = moviesJson.getJSONArray(M_Result);
movieId = new String[resultsArray.length()];
movieTitle = new String[resultsArray.length()];
movieReleaseDate = new String[resultsArray.length()];
movieVoteAverage = new String[resultsArray.length()];
movieOverview = new String[resultsArray.length()];
moviePosterPath = new String[resultsArray.length()];
for (int i = 0; i < resultsArray.length(); i++) {
JSONObject movie = resultsArray.getJSONObject(i);
movieId[i] = movie.getString(M_ID);
movieTitle[i] = movie.getString(M_Title);
movieReleaseDate[i] = movie.getString(M_Release);
movieVoteAverage[i] = movie.getString(M_Vote);
movieOverview[i] = movie.getString(M_OverV);
moviePosterPath[i] = movie.getString(M_Poster);
}
return moviePosterPath;
}
#Override
protected String[] doInBackground(String... params) {
if (params.length == 0) {
return null;
}
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String moviePostersJsonStr = null;
try {
SharedPreferences sharedPreferences = PreferenceManager
.getDefaultSharedPreferences(getActivity());
String sortBy = sharedPreferences.getString(getString(R.string.pref_sortby_key),
getString(R.string.pref_sorting_popularity));
setOrder(sortBy);
final String APPID_PARAM = "api_key";
Uri builtUri = Uri.parse(movieUrl).buildUpon()
.appendQueryParameter(APPID_PARAM, BuildConfig.THE_MOVIE_DB)
.build();
URL url = new URL(builtUri.toString());
Log.v(LOG_TAG, "Built URI " + builtUri.toString());
// Create the request to TheMovieDB, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuilder buffer = new StringBuilder();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line).append("\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
moviePostersJsonStr = buffer.toString();
} catch (IOException e) {
Log.e("PhotoGrid", "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("PhotoGrid", "Error closing stream", e);
}
}
}
try {
return MoviesJasonPrase(moviePostersJsonStr);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String[] Strings) {
if (Strings != null) {
string1 = new String[Strings.length];
for (int i = 0; i < Strings.length; i++) {
//receive poster images path
String[] getImage = Strings[i].split("-");
//concatenate path to url "http://image.tmdb.org/t/p/w185/"
string1[i] = "http://image.tmdb.org/t/p/w185/" + getImage[0];
}
ImageAdapter imageAdapter = new ImageAdapter(getActivity(), string1);
//put images after going though the adapter in the gridview
gridView.setAdapter(imageAdapter);
}
}
}
}
The detailActivity:
public class DetailFragment extends Fragment {
String ID;
String title;
String overView;
String releaseDate;
String rating;
String posterPath;
String movieKey;
databaseHelper myDB ;
ImageButton favorite;
public DetailFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add this line in order for this fragment to handle menu events.
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_detail, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
Intent intent = new Intent(getActivity(), SettingActivity.class);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_detail, container, false);
myDB = new databaseHelper(getActivity(), MovieContract.MovieEntry.TABLE_NAME,null,2);
favorite = (ImageButton) rootView.findViewById(R.id.favorite);
final Intent intent = getActivity().getIntent();
// The detail Activity called via intent. Inspect the intent for
// movies data using movie ID.
if (intent != null && intent.hasExtra("movie_id")) {
//if true put each item in a textview and load the poster in imageView
ID = intent.getStringExtra("movie_id");
title = intent.getStringExtra("movie_title");
((TextView) rootView.findViewById(R.id.title_text))
.setText(title);
overView = intent.getStringExtra("movie_overview");
((TextView) rootView.findViewById(R.id.overview_text))
.setText(overView);
releaseDate = intent.getStringExtra("movie_release_date");
((TextView) rootView.findViewById(R.id.release_date_text))
.setText(releaseDate);
rating = intent.getStringExtra("movie_rating");
((TextView) rootView.findViewById(R.id.rating_text))
.setText(rating);
posterPath = intent.getStringExtra("image_path");
String posterImage = "http://image.tmdb.org/t/p/w185/" + posterPath;
ImageView imageView = (ImageView) rootView.findViewById(R.id.detail_image);
Picasso.with(getActivity()).load(posterImage).resize(500, 800).into(imageView);
}
Button button = (Button) rootView.findViewById(R.id.play);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
playTrailer();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(String.valueOf("http://www.youtube.com/watch?v="+ movieKey)));
startActivity(intent);
}
});
Button button1 = (Button) rootView.findViewById(R.id.open_reviews);
button1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String id = ID;
Intent intent1 = new Intent(getActivity(), ReviewActivity.class);
intent1.putExtra("movie_id", id);
startActivity(intent1);
}
});
addData();
return rootView;
}
public void playTrailer() {
FetchMoviesTrailer fetchMoviesTrailer = new FetchMoviesTrailer();
fetchMoviesTrailer.execute(ID);
}
public void addData(){
favorite.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
boolean isInsearted = myDB.insert(ID, title, overView, releaseDate,
rating, posterPath);
if (isInsearted)
Toast.makeText(getActivity(),"Added to Favorite", Toast.LENGTH_SHORT)
.show();
else
Toast.makeText(getActivity(),"Not Added to Favorite", Toast.LENGTH_SHORT)
.show();
}
}
);
}
public class FetchMoviesTrailer extends AsyncTask<String, Void, String[]> {
private final String LOG_TAG = FetchMoviesTrailer.class.getSimpleName();
//in this function the different order settings are defined
private String[] MoviesJasonPrase(String moviesTrailerStr) throws JSONException {
final String T_Result = "results";
final String T_key = "key";
JSONObject moviesJson = new JSONObject(moviesTrailerStr);
JSONArray resultsArray = moviesJson.getJSONArray(T_Result);
String[] strings = new String[resultsArray.length()];
for (int i = 0; i < resultsArray.length(); i++) {
JSONObject movie = resultsArray.getJSONObject(i);
movieKey = movie.getString(T_key);
strings[i] = movieKey;
}
return strings;
}
#Override
protected String[] doInBackground(String... params) {
if (params.length == 0) {
return null;
}
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String movieTrailerJsonStr = null;
try {
final String APPID_PARAM = "api_key";
final String Traile_Url = "http://api.themoviedb.org/3/movie/" + ID
+ "/videos?";
Uri builtUri = Uri.parse(Traile_Url).buildUpon()
.appendQueryParameter(APPID_PARAM, BuildConfig.THE_MOVIE_DB)
.build();
URL url = new URL(builtUri.toString());
Log.v(LOG_TAG, "Built URI " + builtUri.toString());
// Create the request to TheMovieDB, and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuilder buffer = new StringBuilder();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line).append("\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
movieTrailerJsonStr = buffer.toString();
} catch (IOException e) {
Log.e("PhotoGrid", "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attemping
// to parse it.
return null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("PhotoGrid", "Error closing stream", e);
}
}
}
try {
return MoviesJasonPrase(movieTrailerJsonStr);
} catch (JSONException e) {
Log.e(LOG_TAG, e.getMessage(), e);
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String[] strings) {
super.onPostExecute(strings);
}
}
}
The DataBase Helper:
public class databaseHelper extends SQLiteOpenHelper{
SQLiteDatabase db ;
public static final int DATABASE_VERSION = 2;
public static final String DATABASE_NAME = "FavoriteMovies.db";
public databaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
final String SQL_CREATE_Movie_TABLE = "CREATE TABLE " + MovieEntry.TABLE_NAME + " (" +
MovieEntry.ID_COLUMAN + " TEXT PRIMARY KEY," +
MovieEntry.TITLE_COLUMAN + " TEXT NOT NULL, " +
MovieEntry.OVERVIEW_COLUMAN + " TEXT NOT NULL, " +
MovieEntry.RELEASE_DATE_COLUMAN + " TEXT NOT NULL, " +
MovieEntry.RATING_COLUMAN + " TEXT NOT NULL, " +
MovieEntry.POSTAR_PATH_COLUMAN+ " TEXT NOT NULL " +
" );";
db.execSQL(SQL_CREATE_Movie_TABLE);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS" + MovieEntry.TABLE_NAME);
onCreate(db);
}
public boolean insert(String id, String title , String overView , String date, String rating,
String poster){
db = super.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(MovieEntry.ID_COLUMAN,id);
contentValues.put(MovieEntry.TITLE_COLUMAN,title);
contentValues.put(MovieEntry.OVERVIEW_COLUMAN,overView);
contentValues.put(MovieEntry.RELEASE_DATE_COLUMAN,date);
contentValues.put(MovieEntry.RATING_COLUMAN,rating);
contentValues.put(MovieEntry.POSTAR_PATH_COLUMAN, poster);
long isAdded = db.insert(MovieEntry.TABLE_NAME, null ,contentValues);
if (isAdded == -1) {
return false;
}
else
return true;
}
public Cursor retrieveData(SQLiteDatabase db){
Cursor cursor;
String[] projection = {MovieEntry.ID_COLUMAN, MovieEntry.TITLE_COLUMAN,
MovieEntry.OVERVIEW_COLUMAN, MovieEntry.RELEASE_DATE_COLUMAN, MovieEntry.RATING_COLUMAN,
MovieEntry.POSTAR_PATH_COLUMAN};
cursor = db.query(MovieEntry.TABLE_NAME, projection, null,null,null,null,null);
return cursor;
}
}
The DataBase Contract:
public class MovieContract {
public MovieContract(){}
public static abstract class MovieEntry implements BaseColumns{
public static final String TABLE_NAME = "favorite";
public static final String ID_COLUMAN = "ID";
public static final String TITLE_COLUMAN = "title";
public static final String OVERVIEW_COLUMAN = "overView";
public static final String RELEASE_DATE_COLUMAN = "releaseDate";
public static final String RATING_COLUMAN = "rating";
public static final String POSTAR_PATH_COLUMAN = "posterPath";
}
}
The content Provider:
public class ContentProvider {
private String id;
private String title;
private String overView;
private String releaseDate;
private String rating;
private String posterPath;
public ContentProvider(String ID, String Title,String OverView, String ReleaseDate,
String Rating, String PosterPath){
this.id = ID;
this.title = Title;
this.overView = OverView;
this.releaseDate = ReleaseDate;
this.rating = Rating;
this.posterPath = PosterPath;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getOverView() {
return overView;
}
public void setOverView(String overView) {
this.overView = overView;
}
public String getReleaseDate() {
return releaseDate;
}
public void setReleaseDate(String releaseDate) {
this.releaseDate = releaseDate;
}
public String getRating() {
return rating;
}
public void setRating(String rating) {
this.rating = rating;
}
public String getPosterPath() {
return posterPath;
}
public void setPosterPath(String posterPath) {
this.posterPath = posterPath;
}
}
This is all covered in the Udacity course. I would suggest reviewing those videos.
However, the basic idea is that you need to create a query() method in your content provider class. The Sunshine example from Udacity looks something like this:
#Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
// Here's the switch statement that, given a URI, will determine what kind of request it is,
// and query the database accordingly.
Cursor retCursor;
switch (sUriMatcher.match(uri)) {
// "weather/*/*"
case WEATHER_WITH_LOCATION_AND_DATE:
{
retCursor = getWeatherByLocationSettingAndDate(uri, projection, sortOrder);
break;
}
// "weather/*"
case WEATHER_WITH_LOCATION: {
retCursor = getWeatherByLocationSetting(uri, projection, sortOrder);
break;
}
// "weather"
case WEATHER: {
retCursor = mOpenHelper.getReadableDatabase().query(
WeatherContract.WeatherEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
sortOrder
);
break;
}
// "location"
case LOCATION: {
retCursor = mOpenHelper.getReadableDatabase().query(
WeatherContract.LocationEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
sortOrder
);
break;
}
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
retCursor.setNotificationUri(getContext().getContentResolver(), uri);
return retCursor;
}
From there, if you aren't using a CursorLoader, you need to call the query method on your Content Resolver and pass in your parameters.
Here is an example from Google:
// Queries the user dictionary and returns results
mCursor = getContentResolver().query(
UserDictionary.Words.CONTENT_URI, // The content URI of the words table
mProjection, // The columns to return for each row
mSelectionClause // Selection criteria
mSelectionArgs, // Selection criteria
mSortOrder); // The sort order for the returned rows
I would also take a look at this link to read more about Content Providers.
This is the Java code where I am parsing the data-
pDialog = new ProgressDialog(getActivity());
// Showing progress dialog before making http request
pDialog.setMessage("Loading...Please Wait...");
pDialog.show();
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, "http://sikkimexpress.itstunner.com/api/homenewslist/topnews", new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray("HomeNews");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject homenews = jsonArray.getJSONObject(i);
Movie movie = new Movie();
String newsId = homenews.getString("NewsId");
String dateTime = homenews.getString("DateTime");
String newsType = homenews.getString("NewsType");
String title = homenews.getString("Title");
String description = homenews.getString("Description");
String mainImageURL = homenews.getString("MainImageThumbnail");
movieList.add(movie);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
System.out.println("Result:- " + newsId + " " + dateTime + " " + newsType + " " + title + " " + description + " " + mainImageURL);
}
} catch (JSONException e) {
e.printStackTrace();
}
// pDialog.hide();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("VOLLEY", error.getMessage());
// pDialog.hide();
}
});
AppController.getInstance().addToRequestQueue(jsonObjectRequest);
This is the Model Class:-
public class Movie {
private String newsId;
private String dateTime;
private String newsType;
private String title;
private String description;
private String thumbnailUrl;
public Movie() {
}
public Movie(String news_id, String date_time, String news_type, String news_title, String news_description, String news_thumbnailUrl) {
this.title = news_title;
this.thumbnailUrl = news_thumbnailUrl;
this.newsId = news_id;
this.dateTime = date_time;
this.newsType = news_type;
this.description = news_description;
}
public String getNewsId() {
return newsId;
}
public void setNewsId(String newsId) {
this.newsId = newsId;
}
public String getDateTime() {
return dateTime;
}
public void setDateTime(String dateTime) {
this.dateTime = dateTime;
}
public String getNewsType() {
return newsType;
}
public void setNewsType(String newsType) {
this.newsType = newsType;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getThumbnailUrl() {
return thumbnailUrl;
}
public void setThumbnailUrl(String thumbnailUrl) {
this.thumbnailUrl = thumbnailUrl;
}
}
The CustomListView Adapter:-
public class CustomListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<Movie> movieItems;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public CustomListAdapter(Activity activity, List<Movie> movieItems) {
this.activity = activity;
this.movieItems = movieItems;
}
#Override
public int getCount() {
return movieItems.size();
}
#Override
public Object getItem(int location) {
return movieItems.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.list_row, null);
if (imageLoader == null)
imageLoader = AppController.getInstance().getImageLoader();
NetworkImageView thumbNail = (NetworkImageView) convertView.findViewById(R.id.thumbnail);
TextView title = (TextView) convertView.findViewById(R.id.title);
TextView desciption = (TextView) convertView.findViewById(R.id.desciption);
Movie m = movieItems.get(position);
thumbNail.setImageUrl(m.getThumbnailUrl(), imageLoader);
title.setText(m.getTitle());
desciption.setText(m.getDescription());
return convertView;
}
}
There is no error while Parsing the data from server. I am getting the actual result. But the Progress Dialog is running after getting the data from the server. The data are not getting set in the CustomListView Adapter. I have already attached the code. Please Help me. I got stuck in it.
You are not closing your Dialog when you have your data.
You should not load data on the "main thread" - use a AsyncTask or something similiar to load your data. There you can show a progress dialog, before you start downloading your data:
From the docs:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
//Once created, a task is executed very simply:
new DownloadFilesTask().execute(url1, url2, url3);
Also, don't set the adapter multiple times to your ListView (unless you use a different adapter), and call notifyDataSetChanged() everytime your underlying data changes. r data, show progress and stop the dialog when you are finished.
But the Progress Dialog is running after getting the data from the server.?
ans: you are not closing the dialog in onResponse method
For listview you are not setting adapter with updated data. Please create a new adapter or follow this How to update listview when back pressed from another activity android?
You need to dismiss progressdialog in this two response method to hide.
#Override public void onResponse(JSONObject response) { pDialog.dismiss(); }
#Override public void onErrorResponse(VolleyError error) { pDialog.dismiss(); }
In onResponse() method after parsing json you need to notify adapter to display data in list.
I tried to add textwatcher with filter class but it do not work plz help. I get the json array through the server using the url. the search(filter) doesnt work well.
public class CallDetails extends Activity {
SessionManager session;
ArrayList<Drivers> driverList = new ArrayList<Drivers>();
private List<Drivers> driverlist = null;
ListView listview;
ImageButton btback;
DriverAdapter dadapter;
String uid;
String name;
String email;
String odtyp;
static String oid;
Drivers driver;
private EditText editTextFilter;
private static String OUTBOX_URL ="";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.calldetails);
Intent i = getIntent();
oid =i.getStringExtra("orderId");
odtyp =i.getStringExtra("ordertype");
OUTBOX_URL ="http://www.gdrive.com/api/calldetails.php?id="+oid;
//managing session...
session = new SessionManager(getApplicationContext());
HashMap<String, String> user = session.getUserDetails();
name = user.get(SessionManager.KEY_NAME);
email = user.get(SessionManager.KEY_EMAIL);
uid = user.get(SessionManager.KEY_UID);
btback =(ImageButton)findViewById(R.id.btnBack);
btback.setVisibility(View.INVISIBLE);
// Locate the EditText in listview_main.xml
editTextFilter = (EditText)findViewById(R.id.editTextFilter);
editTextFilter.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable arg0) {
String text = editTextFilter.getText().toString().toLowerCase(Locale.getDefault());
dadapter.filter(text);
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1,
int arg2, int arg3){ /* to do*/ }
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) { /*to do*/ }
});
//populating view with data...
//driverList = new ArrayList<Drivers>();
new JSONAsyncTask().execute(OUTBOX_URL);
listview = (ListView)findViewById(R.id.drlist);
dadapter = new DriverAdapter(CallDetails.this, R.layout.list_item, driverList);
listview.setItemsCanFocus(false);
listview.setAdapter(dadapter);
//populating list ends
listview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long id) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), driverList.get(position).getName(), Toast.LENGTH_LONG).show();
}
});
}
public void back(View v){
Intent back = new Intent(getApplicationContext(), SafetyDrive.class);
startActivity(back);
finish();
}
private class DriverAdapter extends ArrayAdapter<Drivers> {
Context context;
int Resource;
LayoutInflater inflater;
ArrayList<Drivers> driverList = new ArrayList<Drivers>();
public DriverAdapter(Context context, int layoutResourceId,ArrayList<Drivers> drs) {
super(context, layoutResourceId, drs);
//inflater = ((Activity) context).getLayoutInflater();
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Resource = layoutResourceId;
driverList = drs;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//Log.d("in ", "view start");
View item = convertView;
DriverWrapper DriverWrapper = null;
if (item == null) {
DriverWrapper = new DriverWrapper();
item = inflater.inflate(Resource, null);
DriverWrapper.ename = (TextView) item.findViewById(R.id.textName);
DriverWrapper.ephone = (TextView) item.findViewById(R.id.textPhone);
DriverWrapper.mkcall = (ImageButton) item.findViewById(R.id.btnphone);
item.setTag(DriverWrapper);
} else {
DriverWrapper = (DriverWrapper) item.getTag();
}
Drivers driver = driverList.get(position);
DriverWrapper.ename.setText("Name: " + driver.getName());
DriverWrapper.ephone.setText("Phone: " + driver.getPhone());
final String dp = driver.getPhone().trim();
DriverWrapper.mkcall.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//making call..
//Log.e("no is", dp);
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:" +dp));
//callIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(callIntent);
//finish();
}
});
return item;
}
class DriverWrapper {
TextView ename;
TextView ephone;
ImageButton mkcall;
//ImageButton msg;
}
// Filter Class
public void filter(String charText) {
charText = charText.toLowerCase(Locale.getDefault());
driverList.clear();
if (charText.length() == 0) {
driverList.addAll(driverList);
} else {
for (Drivers driver : driverList) {
if (driver.getName().toLowerCase(Locale.getDefault()).contains(charText)) {
driverList.add(driver);
}
}
}
notifyDataSetChanged();
}
}
class JSONAsyncTask extends AsyncTask {
ProgressDialog dialog;
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(CallDetails.this);
dialog.setMessage("Loading, please wait");
dialog.show();
dialog.setCancelable(false);
}
#Override
protected Boolean doInBackground(String... urls) {
try {
//Log.d("in at-", "asynctask");
HttpGet httppost = new HttpGet(urls[0]);
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(httppost);
// StatusLine stat = response.getStatusLine();
int status = response.getStatusLine().getStatusCode();
if (status == 200) {
HttpEntity entity = response.getEntity();
String data = EntityUtils.toString(entity);
JSONObject jsono = new JSONObject(data);
JSONArray jarray = jsono.getJSONArray("drivers");
if(jarray.length()!=0){
for (int i = 0; i < jarray.length(); i++) {
JSONObject object = jarray.getJSONObject(i);
Drivers driver = new Drivers();
driver.setPhone(object.getString("phone"));
driver.setName(object.getString("emp_name"));
driverList.add(driver);
}
}else{
driver = new Drivers();
driver.setPhone(" ");
driver.setName(" No Driver Place yet");
driverList.add(driver);
}
return true;
}
} catch (ParseException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
protected void onPostExecute(Boolean result) {
dialog.cancel();
btback.setVisibility(View.VISIBLE);
dadapter.notifyDataSetChanged();
if(result == false)
Toast.makeText(getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG).show();
}
}
}
public class Drivers {
private String name;
private String phone;
public Drivers() {
}
public Drivers(String name, String phone) {
super();
this.name = name;
this.phone = phone;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
actually it wont filter because youve cleared the driverList and then in the else statement you loop to driverList which is already empty. the only thing you can do is create a backup list for the driversList and then use the backup list to get all data for filtering to the driverList.
Example Here:
// here is the backuplist
ArrayList<Drivers> backupList = new ArrayList<Drivers>();
// Filter Class
public void filter(String charText) {
charText = charText.toLowerCase(Locale.getDefault());
// actually its easy to just clear the backup list
// but due to reasons where users press backspace you have to load backup list only once
if(backupList.isEmpty()) {
backupList.addAll(driverList);
}
driverList.clear();
if (charText.length() == 0) {
driverList.addAll(backupList);
} else {
for (Drivers driver : backupList) {
if (driver.getName().toLowerCase(Locale.getDefault()).contains(charText)) {
driverList.add(driver);
}
}
}
notifyDataSetChanged();
}
Hope it helps :)