Greetings in advance to all the people here.
I have been wandering between the problem and the madness while I was finding the solution to my problem, I have already invested more of the time possible in solving my dilemma, now I need the most knowledgeable in the subject to help me.
As I detail below, what I'm doing or at least trying to do is updating a RecyclerView
while I'm collecting certain data that is being saved in the DB
and in the list of elements
.
The data that I'm going to paint in the RecyclerView
, I get it in the following way, with rssparser
I first get a list of links that later with Jsoup
, I get images and text of the news.
It happens that these functions that use interaction with the network have to be called inside threads
that are not those of the UI, and good I believe that I have created there like multithreading, and good the function that does this obtaining of data I could within a asynchronous task.
Another thing I need is for the progress bubble
in this view to be maintained until the processing of the threads is finished. Ideally it would work in real time, I have done it but it does not work for me by adding each new element to the list and notifying the adapter of a new inserted item.
When the processing of the task ends, and the threads complete their work, I do not update the RecyclerView
with adapter.notifyDatasetChanged()
either, I do not know what else to try, maybe I have some algorithmic error.
Below I'm going to put my code, I apologize for my trail, sure I have left some little unnecessary code or commented.
The Fragment:
public class ViewerNewsFragment1 extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String ARG_COLUMN_COUNT = "column-count";
private int mColumnCount = 1;
private OnListFragmentInteractionListener mListener;
private static final String ARG_PARAM1 = "id";
// TODO: Rename and change types of parameters
private Integer mParam1;
private String finalUrl;
private ViewerNewsRecyclerViewAdapter adapter;
private SwipeRefreshLayout swipeView;
private TextView connectionError;
private int imageHolder;
private NewsHelper newsHelper;
private String SENT_ = "SMS_SENT_SUSCRIPTION_";
private String DELIVERED_ = "SMSDELIVERED_SUSCRIPTION_";
private BroadcastReceiver sendBroadcastReceiver;
private BroadcastReceiver deliveryBroadcastReceiver;
List<News> news = new ArrayList<>();
private boolean flag = false;
OkHttpClient client;
private boolean isAlreadyRefresh;
public ViewerNewsFragment1() {
}
public static ViewerNewsFragment1 newInstance(int columnCount, Integer id) {
ViewerNewsFragment1 fragment = new ViewerNewsFragment1();
Bundle args = new Bundle();
args.putInt(ARG_COLUMN_COUNT, columnCount);
args.putInt(ARG_PARAM1, id);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
newsHelper = new NewsHelper(getActivity());
if (getArguments() != null) {
mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT);
mParam1 = getArguments().getInt(ARG_PARAM1);
DummyContent.DummyItem item = DummyContent.ITEMS.get(new Integer(mParam1) - 1);
finalUrl = item.url;
imageHolder = item.smallimage;
}
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
private boolean isNetworkAvailable() {
ConnectivityManager connectivityManager = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_viewer_news_list, container, false);
// Set the adapter
Context context = view.getContext();
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recycler_news);
recyclerView.setLayoutManager(new LinearLayoutManager(context));
adapter = new ViewerNewsRecyclerViewAdapter(news, mListener, imageHolder, newsHelper.getNewsDao());
recyclerView.setAdapter(adapter);
swipeView = (SwipeRefreshLayout) view.findViewById(R.id.swipe);
swipeView.setOnRefreshListener(this);
swipeView.setProgressViewOffset(false, 0,
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, getResources().getDisplayMetrics()));
connectionError = (TextView) view.findViewById(R.id.connection_error);
setRetainInstance(true);
Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.acerca_toolbar);
toolbar.setBackgroundColor(Color.parseColor("#f2f2f2"));
ImageView iv = (ImageView) toolbar.findViewById(R.id.iconToShow);
toolbar.getContext().setTheme(R.style.AppTheme2);
int img_bar = R.drawable.appbar_cubadebate;
SharedPreferences preferences = ((ViewerActivity) mListener).getSharedPreferences("client_data", Context.MODE_WORLD_WRITEABLE);
SharedPreferences.Editor ed = preferences.edit();
if (mParam1.equals(1)) {
ed.putInt("cubadebate", 0);
ed.commit();
img_bar = R.drawable.appbar_cubadebate;
} else if (mParam1.equals(2)) {
ed.putInt("granma", 0);
ed.commit();
img_bar = R.drawable.appbar_granma;
} else if (mParam1.equals(3)) {
ed.putInt("prela", 0);
ed.commit();
img_bar = R.drawable.appbar_pl;
}
iv.setImageResource(img_bar);
isAlreadyRefresh = false;
setHasOptionsMenu(true);
Dao<News, Integer> dao = newsHelper.getNewsDao();
try {
QueryBuilder<News, Integer> builder = newsHelper.getNewsDao().queryBuilder();
builder.where().eq("author", mParam1.toString());
builder.limit(20);
builder.orderBy("newsDate", false); // true for ascending, false for descending
news = dao.query(builder.prepare());
}catch (Exception e){
e.printStackTrace();
}
adapter.setmValues(news);
adapter.notifyDataSetChanged();
return view;
}
private void fetchNews() {
fetchInternalNews();
if (isNetworkAvailable()) {
Cache cache = new Cache(getContext().getCacheDir(), Integer.MAX_VALUE);
client = new OkHttpClient.Builder()
.addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder().header("Cache-Control", "max-age=" + (60 * 60 * 24 * 365)).build();
}
})
.cache(cache)
.build();
Parser parser = new Parser();
parser.execute(finalUrl);
parser.onFinish(new Parser.OnTaskCompleted() {
@Override
public void onTaskCompleted(final ArrayList<Article> list) {
new LongOperation().execute(list);
}
@Override
public void onError() {
if (getActivity() != null)
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
swipeView.setRefreshing(false);
connectionError.setVisibility(View.VISIBLE);
isAlreadyRefresh = false;
}
});
}
});
} else {
swipeView.setRefreshing(false);
Toast.makeText(getContext(), "No tiene conexión a Internet. Active la Wi-Fi o los datos móviles, y vuelva a intentarlo.", Toast.LENGTH_LONG).show();
}
}
private class LongOperation extends AsyncTask<List<Article>, Void, String> {
@Override
protected String doInBackground(List<Article>... lists) {
swipeView.setRefreshing(true);
GoScrapp(lists[0]);
return "Executed";
}
@Override
protected void onPostExecute(String result) {
adapter.notifyDataSetChanged();
isAlreadyRefresh = true;
swipeView.setRefreshing(false);
}
}
public void GoScrapp(List<Article> list){
Dao<News, Integer> dao = newsHelper.getNewsDao();
News t = new News();
List<News> news_list = new ArrayList<>();
try {
QueryBuilder<News, Integer> builder = newsHelper.getNewsDao().queryBuilder();
builder.where().eq("author", mParam1.toString());
builder.limit(20);
builder.orderBy("newsDate", false); // true for ascending, false for descending
news_list = dao.query(builder.prepare());
}catch (Exception e){
e.printStackTrace();
}
boolean esta = false;
for (Article article : list) {
if(!news_list.isEmpty())
for (News item : news_list) {
if(item.getLink().equals(article.getLink())){
esta = true;
}
}else esta = false;
if(!esta) {
Foo foo = new Foo(article);
Thread th = new Thread(foo);
try {
th.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private void fetchInternalNews() {
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnListFragmentInteractionListener) {
mListener = (OnListFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnListFragmentInteractionListener");
}
}
@Override
public void onResume() {
super.onResume();
onRefresh();
//Todo:Puse este valor en true, estaba en false
isAlreadyRefresh = true;
}
@Override
public void onDetach() {
super.onDetach();
}
@Override
public void onRefresh() {
if (!isAlreadyRefresh) {
swipeView.setRefreshing(true);
swipeView.postDelayed(new Runnable() {
@Override
public void run() {
fetchNews();
isAlreadyRefresh = true;
adapter.setmValues(news);
}
}, 1000);
} else
swipeView.setRefreshing(false);
}
public interface OnListFragmentInteractionListener {
void onListFragmentInteraction(Integer id);
}
private boolean CanSuscribe(){
NewsHelper helper = new NewsHelper(getContext());
SuscriptionRequest sr_object;
Date today = new Date();
boolean result;
try {
if(!helper.getSuscriptionRequestDao().queryForEq(SuscriptionRequest.FUENTE, mParam1).isEmpty())
{
sr_object = helper.getSuscriptionRequestDao().queryForEq(SuscriptionRequest.FUENTE, mParam1).get(0);
//get the date of usscription
Date date = sr_object.getFecha();
Calendar calendar = new GregorianCalendar(/* remember about timezone! */);
calendar.setTime(date);
calendar.add(Calendar.DATE, 30);
date = calendar.getTime();
result = today.after(date);
} else {
result = true;
}
}catch (SQLException e) {
Log.e("ERROR Saving SR", e.getMessage());
result = false;
}
return result;
}
private void SaveSuscriptionRequest(){
NewsHelper helper = new NewsHelper(getContext());
SuscriptionRequest sr = new SuscriptionRequest();
try{
if(!helper.getSuscriptionRequestDao().queryForEq(SuscriptionRequest.FUENTE, mParam1).isEmpty()) {
sr.setFecha(new Date());
sr.setFuente(mParam1);
helper.getSuscriptionRequestDao().create(sr);
} else {
sr = helper.getSuscriptionRequestDao().queryForEq(SuscriptionRequest.FUENTE, mParam1).get(0);
sr.setFecha(new Date());
helper.getSuscriptionRequestDao().update(sr);
}
} catch (SQLException e) {
Log.e("ERROR Saving SR", e.getMessage());
}
}
public void sendMessage(String phoneNumber, String message) {
final Activity mContext = (Activity) mListener;
PendingIntent sentPI = PendingIntent.getBroadcast(mContext, 0, new Intent(SENT_), 0);
PendingIntent deliveredPI = PendingIntent.getBroadcast(mContext, 0, new Intent(DELIVERED_), 0);
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, message, sentPI, deliveredPI);
}
@Override
public void onPause() {
super.onPause();
if(flag) {
myOnDestroy();
}
}
public class Foo implements Runnable {
private volatile String value;
private String url;
private Article article;
public Foo(Article article){
this.url = article.getLink();
this.article = article;
}
@Override
public void run() {
final StringBuilder builder = new StringBuilder();
OkHttp3Downloader okHttpDownloader = new OkHttp3Downloader(client);
Picasso picasso = new Picasso.Builder(getContext()).downloader(okHttpDownloader).build();
try {
Document doc = Jsoup.connect(url).get();
Elements links = new Elements();
Elements img = new Elements();
String img_url = "";
switch (mParam1){
case 1:
links = doc.select("div[class=note_content] > p");
img = doc.select("div[id^=\"attachment_\"] > img");
if(!img.isEmpty())
{
img_url = img.first().attr("srcset").split(" ")[0];
if(img_url.isEmpty())
img_url = img.first().attr("src");
if(!img_url.isEmpty()) picasso.with(getContext()).load(img_url).fetch();
}
break;
case 2:
links = doc.select("div[class=story-body-text story-content] > p");
img = doc.select("div[class=image] > img");
if(!img.isEmpty()){
img_url = "http://www.granma.cu"+img.first().attr("src");
Log.e("URL", img_url);
if(!img_url.isEmpty()) picasso.with(getContext()).load(img_url).fetch();
}
break;
case 3:
links = doc.select("div[class=fullNewsFulltext]");
img = doc.select("div[class=fullNewsIntrotext] img");
if(!img.isEmpty()){
img_url = "http://prensa-latina.cu"+img.first().attr("src");
Log.e("URL", img_url);
if(!img_url.isEmpty()) picasso.with(getContext()).load(img_url).fetch();
}
break;
}
for (Element link : links) {
builder.append(link.text()).append("\n");
}
value = article.getLink();
Dao<News, Integer> dao = newsHelper.getNewsDao();
News t = new News();
String author = "";
t.setTitle(article.getTitle());
t.setAuthor(mParam1.toString());
t.setDescription(article.getDescription());
t.setLink(article.getLink());
t.setCompleteDescription(builder.toString());
t.setImage(article.getImage());
t.setImage_link(img_url);
if (article.getPubDate() != null)
t.setNewsDate(article.getPubDate());
else {
final SimpleDateFormat sf = new SimpleDateFormat("dd/MM/yyyy hh:mm");
try {
t.setNewsDate(sf.parse(sf.format(new Date())));
} catch (Exception e) {
Log.e("ERROR FECHA", e.getMessage());
}
}
try {
List<News> existing = dao.queryForEq("title", t.getTitle());
if (existing.size() == 0) {
dao.create(t);
news.add(t);
Log.e("ERROR FECHA", "ADD"+t.getTitle());
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
// Stuff that updates the UI
adapter.notifyItemInserted(news.size() - 1);
// adapter.notifyDataSetChanged();
// swipeView.setRefreshing(true);
}
});
// adapter.notifyDataSetChanged();
}
} catch (SQLException e) {
Log.e("ERROR", e.getMessage());
}
} catch (IOException e) {
builder.append("Error : ").append(e.getMessage()).append("\n");
}
}
public String getValue() {
return value;
}
}
public void myOnDestroy(){
final Activity mContext = (Activity) mListener;
mContext.unregisterReceiver(sendBroadcastReceiver);
mContext.unregisterReceiver(deliveryBroadcastReceiver);
}
}
Besides adityakamble49's answer. The problem might be located here inside GoScrapp function:
if(!esta) {
Foo foo = new Foo(article);
Thread th = new Thread(foo);
try {
th.start();
} catch (Exception e) {
e.printStackTrace();
}
}
you are starting a new thread inside doInBackground() that process the data and updates the DB, so onPostExecute() is executed before the thread inserts the data to the DB.