Close Menu
InfovistarInfovistar
  • AI & ML
  • Cybersecurity
  • Startup
  • Tech News
  • Insights
    • Web Development
    • AWS and Cloud
    • Blockchain and Cryptocurrency
    • Chatbots
    • Technology
    • DevOps
    • Resources
  • Courses
    • Machine Learning
      • Python Tutorial
      • TensorFlow Tutorial
      • OpenCV
    • DSA
      • Data Structures
    • Web Development
      • PHP Tutorial
      • CodeIgniter Tutorial
      • CodeIgniter 4 Tutorial
      • CodeIgniter 4 AJAX
      • JavaScript
    • Mobile Development
      • Android Tutorial
  • Tools
    • Beautifier
      • HTML Beautifier
      • JavaScript Beautifier
      • CSS Beautifier
    • Online Compilers
      • Python Compiler
      • Java Compiler
      • JavaScript Editor
      • PHP Compiler
      • C++ Compiler
      • C Compiler
    • Image Optimization
      • Image Compressor
      • JPEG to PNG
      • PNG to JPEG
      • WebP to PNG

Subscribe to Updates

Get the latest creative news from FooBar about art, design and business.

What's Hot

Ransomware 2.0: How AI Is Changing Cyber Attacks Forever

April 18, 2025

Lovable AI Faces Major Threat from VibeScamming Attacks

April 10, 2025

Top Trends to Include in Your Strategy for Digital Marketing in 2025

April 5, 2025
Facebook X (Twitter) Instagram
Facebook X (Twitter) Instagram Pinterest Vimeo
InfovistarInfovistar
  • AI & ML
  • Cybersecurity
  • Startup
  • Tech News
  • Insights
    • Web Development
    • AWS and Cloud
    • Blockchain and Cryptocurrency
    • Chatbots
    • Technology
    • DevOps
    • Resources
  • Courses
    • Machine Learning
      • Python Tutorial
      • TensorFlow Tutorial
      • OpenCV
    • DSA
      • Data Structures
    • Web Development
      • PHP Tutorial
      • CodeIgniter Tutorial
      • CodeIgniter 4 Tutorial
      • CodeIgniter 4 AJAX
      • JavaScript
    • Mobile Development
      • Android Tutorial
  • Tools
    • Beautifier
      • HTML Beautifier
      • JavaScript Beautifier
      • CSS Beautifier
    • Online Compilers
      • Python Compiler
      • Java Compiler
      • JavaScript Editor
      • PHP Compiler
      • C++ Compiler
      • C Compiler
    • Image Optimization
      • Image Compressor
      • JPEG to PNG
      • PNG to JPEG
      • WebP to PNG
Subscribe
InfovistarInfovistar
Home » Endless Scrolling with RecyclerView using Retrofit in Android
Android

Endless Scrolling with RecyclerView using Retrofit in Android

InfovistarBy InfovistarApril 3, 2022Updated:November 21, 2024No Comments7 Mins Read
Share Facebook Twitter Pinterest LinkedIn Tumblr Reddit Telegram Email
Endless Scrolling with RecyclerView using Retrofit in Android
Share
Facebook Twitter LinkedIn Pinterest Email

This tutorial will teach you how to implement Endless Scrolling in Android applications using RecyclerViews. An infinite scroll displays the loading icon while new records are pulled from the database. Many applications, such as Facebook and Twitter, use this type of loading.

Android RecyclerView Load More

For the Loading icon to appear at the bottom of RecyclerView, we need to use multiple view types in our Android Application.

The RecyclerView needs to implement OnScrollListener() to detect when the user has scrolled to the end.

We will demonstrate Endless Scrolling with RecyclerView by populating a List of Items and loading the next set of Items.

Project Structure

Project Structure Endless Scrolling
Project Structure Endless Scrolling

Code

Let’s take a look at the activity_main.xml layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <include
        layout="@layout/toolbar"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_transaction"
            android:layout_above="@id/bottom_progress_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

        <include
            layout="@layout/bottom_progress_bar"
            android:id="@+id/bottom_progress_layout"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_alignParentBottom="true"
            android:visibility="gone"/>

        <include
            layout="@layout/center_progress_bar"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:layout_centerInParent="true"
            android:visibility="gone"/>

        <include
            layout="@layout/no_product_dialog"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:layout_centerInParent="true"
            android:visibility="gone"/>

    </RelativeLayout>

</LinearLayout>

The layout_transaction.xml layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/margin_8">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:weightSum="2"
        android:padding="@dimen/padding_12">

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical"
            android:layout_marginEnd="@dimen/margin_4">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Transaction Number"
                android:textColor="@color/black"
                android:textSize="15sp"
                android:textStyle="bold"/>

            <TextView
                android:id="@+id/tv_transaction_number"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Transaction Number"
                android:textColor="@color/black"
                android:textSize="15sp"
                android:layout_marginTop="@dimen/margin_4"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Client Name"
                android:textColor="@color/black"
                android:textSize="15sp"
                android:layout_marginTop="@dimen/margin_8"
                android:textStyle="bold"/>

            <TextView
                android:id="@+id/tv_client_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Client Name"
                android:textColor="@color/black"
                android:textSize="15sp"
                android:layout_marginTop="@dimen/margin_4"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical"
            android:layout_marginStart="@dimen/margin_4">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Date"
                android:textColor="@color/black"
                android:textSize="15sp"
                android:textStyle="bold"/>

            <TextView
                android:id="@+id/tv_date"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Date"
                android:textColor="@color/black"
                android:textSize="15sp"
                android:layout_marginTop="@dimen/margin_4"/>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Amount"
                android:textColor="@color/black"
                android:textSize="15sp"
                android:textStyle="bold"
                android:layout_marginTop="@dimen/margin_8"/>

            <TextView
                android:id="@+id/tv_amount"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Amount"
                android:textColor="@color/black"
                android:textSize="15sp"
                android:layout_marginTop="@dimen/margin_4"/>

        </LinearLayout>

    </LinearLayout>

</androidx.cardview.widget.CardView>

Let’s take a look at the center_progress_bar.xml :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingTop="@dimen/padding_16"
    android:paddingBottom="@dimen/padding_16"
    android:paddingStart="@dimen/padding_32"
    android:paddingEnd="@dimen/padding_32"
    android:orientation="vertical"
    android:id="@+id/center_progress_layout">

    <ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:layout_gravity="center" />

    <TextView
        android:id="@+id/progress_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/margin_8"
        android:gravity="center_vertical"
        android:text="Loading ..."
        android:textColor="@color/GBL1_5"
        android:textSize="15sp"
        android:layout_gravity="center"/>

</LinearLayout>

The bottom_progress_bar.xml layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingTop="@dimen/padding_16"
    android:paddingBottom="@dimen/padding_16"
    android:paddingStart="@dimen/padding_32"
    android:paddingEnd="@dimen/padding_32"
    android:orientation="vertical"
    android:id="@+id/bottom_progress_layout">

    <ProgressBar
        android:id="@+id/progress_bar"
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:layout_gravity="center" />

    <TextView
        android:id="@+id/progress_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/margin_8"
        android:gravity="center_vertical"
        android:text="Loading ..."
        android:textColor="@color/GBL1_5"
        android:textSize="15sp"
        android:layout_gravity="center"/>

</LinearLayout>

Let’s take a look at the MainActivity.java class where we create and instantiate the Adapter.

package com.infovistar.recylerviewexample;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MainActivity extends AppCompatActivity {

    private Toolbar toolbar;
    private TextView toolbarTitle;

    private RecyclerView rvTransaction;
    private LinearLayout centerProgressLayout;
    private LinearLayout bottomProgressLayout;
    private LinearLayout noItemLayout;
    private LinearLayoutManager layoutManager;

    private ApiService apiService;
    private int startId     = 0;
    private int indexId     = 0;
    private int loadLimit   = 50;
    private List<TransactionResultModel> resultModelList;
    private TransactionAdapter transactionAdapter;

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

        init();

        loadTransactionList(startId);
        rvTransaction.addOnScrollListener(new RecyclerView.OnScrollListener() {

            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if (dy > 0) {
                    if (!recyclerView.canScrollVertically(RecyclerView.FOCUS_DOWN)) {
                        layoutManager.scrollToPosition(resultModelList.size() - 1);
                        indexId++;
                        startId = loadLimit * indexId;
                        loadTransactionList(startId);
                    }
                }
            }
        });
    }

    private void loadTransactionList(int startId) {
        if(startId == 0) {
            centerProgressLayout.setVisibility(View.VISIBLE);
            rvTransaction.setVisibility(View.GONE);
            noItemLayout.setVisibility(View.GONE);
            bottomProgressLayout.setVisibility(View.GONE);
        } else {
            bottomProgressLayout.setVisibility(View.VISIBLE);
        }
        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("start_limit", startId);
        hashMap.put("load_limit", loadLimit);
        apiService
                .getTransactionList(hashMap)
                .enqueue(new Callback<TransactionModel>() {
                    @Override
                    public void onResponse(Call<TransactionModel> call, Response<TransactionModel> response) {
                        if(response.body() != null) {
                            if(response.body().getStatus()) {
                                if(startId == 0) {
                                    centerProgressLayout.setVisibility(View.GONE);
                                    rvTransaction.setVisibility(View.VISIBLE);
                                    noItemLayout.setVisibility(View.GONE);
                                }
                                bottomProgressLayout.setVisibility(View.GONE);
                                populateTransactionList(response.body().getResult());
                            } else {
                                if(startId == 0) {
                                    centerProgressLayout.setVisibility(View.GONE);
                                    centerProgressLayout.setVisibility(View.GONE);
                                    noItemLayout.setVisibility(View.VISIBLE);
                                }
                                bottomProgressLayout.setVisibility(View.GONE);
                            }
                        }
                    }

                    @Override
                    public void onFailure(Call<TransactionModel> call, Throwable t) {
                        if(startId == 0) {
                            centerProgressLayout.setVisibility(View.GONE);
                            centerProgressLayout.setVisibility(View.GONE);
                            noItemLayout.setVisibility(View.VISIBLE);
                        }
                        bottomProgressLayout.setVisibility(View.GONE);
                    }
                });
    }

    private void populateTransactionList(List<TransactionResultModel> result) {
        resultModelList.addAll(result);
        transactionAdapter.notifyDataSetChanged();
    }

    private void init() {
        toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        toolbarTitle = findViewById(R.id.toolbar_title);
        toolbarTitle.setText(getString(R.string.app_name));

        rvTransaction           = findViewById(R.id.rv_transaction);
        centerProgressLayout    = findViewById(R.id.center_progress_layout);
        noItemLayout            = findViewById(R.id.no_item_layout);
        bottomProgressLayout    = findViewById(R.id.bottom_progress_layout);
        layoutManager           = new LinearLayoutManager(this);
        rvTransaction.setLayoutManager(layoutManager);
        rvTransaction.setHasFixedSize(true);
        resultModelList         = new ArrayList<>();
        transactionAdapter      = new TransactionAdapter(resultModelList);
        rvTransaction.setAdapter(transactionAdapter);

        apiService              = ApiRequestHelper.getApiClient(this).create(ApiService.class);
    }
    
    class TransactionAdapter extends RecyclerView.Adapter<TransactionAdapter.ViewHolder> {
        
        private List<TransactionResultModel> resultModelList;
        
        public TransactionAdapter(List<TransactionResultModel> resultModelList) {
            this.resultModelList = resultModelList;
        }

        @NonNull
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_transaction, parent, false);
            return new ViewHolder(view);
        }

        @Override
        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
            TransactionResultModel resultModel = resultModelList.get(position);
            holder.setTransactionNumber(resultModel.getTransactionNumber());
            holder.setVendorName(resultModel.getVendorName());
            holder.setReceiveDate(resultModel.getReceiveDate());
            holder.setCurrencyAmount(resultModel.getCurrencyAmount() + " " + resultModel.getCurrency());
        }

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

        public class ViewHolder extends RecyclerView.ViewHolder {

            private TextView tvTransactionNumber;
            private TextView tvClientName;
            private TextView tvDate;
            private TextView tvAmount;


            public ViewHolder(@NonNull View itemView) {
                super(itemView);

                tvTransactionNumber = itemView.findViewById(R.id.tv_transaction_number);
                tvClientName        = itemView.findViewById(R.id.tv_client_name);
                tvDate              = itemView.findViewById(R.id.tv_date);
                tvAmount            = itemView.findViewById(R.id.tv_amount);
            }

            public void setTransactionNumber(String transactionNumber) {
                tvTransactionNumber.setText(transactionNumber);
            }

            public void setVendorName(String vendorName) {
                tvClientName.setText(vendorName);
            }

            public void setReceiveDate(String receiveDate) {
                tvDate.setText(receiveDate);
            }

            public void setCurrencyAmount(String amount) {
                tvAmount.setText(amount);
            }
        }
    }
}

The addOnScrollListener() is the most important method in the above code.

The next list is populated if the bottom-most item is visible in RecyclerView.

The onBindViewHolder() is called to display the data at the specified position. It is used to update the contents of the RecyclerView to reflect the item at the given position.

Retrofit

Retrofit is a Java and Android library for type-safe HTTP networking. The retrofit is super fast, has better functionality, and has a simpler syntax.

Advantages of Retrofit

  • Manages the process of receiving, sending, and creating HTTP requests and responses.
  • Alternates IP addresses if there is a connection to a web service failure.
  • Caches responses to avoid sending duplicate requests.
  • Pools connections to reduce latency.

Classes used in retrofit

  • Model class – This class contains the objects from the JSON file. For example, TransactionModel.java and TransactionResultModel.java
  • Retrofit instance – Used to send requests to an API. For example, ApiRequestHelper.java
  • Interface class – Used to define endpoints. For example, ApiService.java

The ApiRequestHelper.java file

package com.infovistar.recylerviewexample;

import android.content.Context;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import okhttp3.Cache;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class ApiRequestHelper {

    public static final String WEB_URL = "https://infovistar.com/";
    public static final String BASE_URL = WEB_URL+"api/v1/";
    public static Retrofit retrofit = null;
    public static Context context;

    private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Response originalResponse = chain.proceed(chain.request());
            if (NetworkDetector.isNetworkAvailable(context)) {
                int maxAge = 60; // read from cache for 1 minute
                return originalResponse.newBuilder()
                        .header("Cache-Control", "public, max-age=" + maxAge)
                        .build();
            } else {
                int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
                return originalResponse.newBuilder()
                        .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                        .build();
            }
        }
    };

    //setup cache
    public static File httpCacheDirectory = new File(context != null ? context.getCacheDir() : null, "responses");
    public static int cacheSize = 10 * 1024 * 1024; // 10 MiB
    public static Cache cache = new Cache(httpCacheDirectory, cacheSize);

    public static final OkHttpClient clientOkHttp = new OkHttpClient().newBuilder()
            .readTimeout(120, TimeUnit.SECONDS)
            .connectTimeout(120, TimeUnit.SECONDS)
            .addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
            .cache(cache)
            .build();

    public static Retrofit getApiClient() {
        if(retrofit == null) {
            retrofit = new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).client(clientOkHttp).build();
        }
        return retrofit;
    }

    public static Retrofit getApiClient(Context ctx) {
        if(retrofit == null) {
            OkHttpClient client;
            try {
                CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
                InputStream inputStream = ctx.getResources().openRawResource(R.raw.infovistarcom);
                Certificate certificate = certificateFactory.generateCertificate(inputStream);
                String keyStoreType = KeyStore.getDefaultType();
                KeyStore keyStore = KeyStore.getInstance(keyStoreType);
                keyStore.load(null, null);
                keyStore.setCertificateEntry("ca", certificate);
                String defAlgo = TrustManagerFactory.getDefaultAlgorithm();
                TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(defAlgo);
                trustManagerFactory.init(keyStore);
                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, trustManagerFactory.getTrustManagers(), null);

                client = new OkHttpClient()
                        .newBuilder()
                        .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustManagerFactory.getTrustManagers()[0])
                        .readTimeout(120, TimeUnit.SECONDS)
                        .connectTimeout(120, TimeUnit.SECONDS)
                        .addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
                        .cache(cache)
                        .build();
                retrofit = new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).client(client).build();
            } catch (CertificateException | KeyStoreException | IOException | NoSuchAlgorithmException | KeyManagementException e) {
                e.printStackTrace();
                retrofit = new Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create()).client(clientOkHttp).build();
            }
            context = ctx;
        }
        return retrofit;
    }
}

The ApiService.java file

package com.infovistar.recylerviewexample;


import java.util.HashMap;

import retrofit2.Call;
import retrofit2.http.FieldMap;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;

public interface ApiService {

    @FormUrlEncoded
    @POST("transaction/list")
    Call<TransactionModel> getTransactionList(@FieldMap HashMap<String, Object> hashMap);

}

Output:

Endless Scrolling Output

Source code: Download

Android endless scrolling retrofit
Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
Previous ArticleBest Blockchain Programming Languages for Developers
Next Article Is Blockchain Secure? in Hindi
Infovistar
  • Website
  • Facebook
  • X (Twitter)
  • Instagram
  • LinkedIn

Related Posts

Tech Tips

What Is Google Partner Setup and How Does It Work?

February 28, 2025
Tech News

Google is rolling out Identity Check Feature to Android 15

January 25, 2025
Cybersecurity

Google’s New Restore Credentials Tool Simplifies App Login

November 26, 2024
Add A Comment

Comments are closed.

Blog Categories
  • AI and ML (93)
  • Android (4)
  • AWS and Cloud (7)
  • Blockchain and Cryptocurrency (6)
  • Case Study (7)
  • Chatbots (5)
  • Cybersecurity (71)
  • DevOps (5)
  • Object-Oriented Programming (2)
  • Payment Gateway (4)
  • Resources (5)
  • Search Engine Optimization (3)
  • Startup (34)
  • Tech News (70)
  • Tech Tips (12)
  • Technology (79)
  • Trading (6)
  • Web Development (23)
Top Posts

Google is rolling out Identity Check Feature to Android 15

January 25, 20252,370 Views

How to Integrate Google Gemini to WhatsApp

February 16, 20241,658 Views

OpenAI Unveils Web-Based AI Agent Operator for Task Automation

January 24, 20251,502 Views
Stay In Touch
  • Facebook
  • YouTube
  • WhatsApp
  • Twitter
  • Instagram
  • Pinterest
  • LinkedIn
Latest Articles

Subscribe to Updates

Get the latest tech news from FooBar about tech, design and biz.

Most Popular

Google is rolling out Identity Check Feature to Android 15

January 25, 20252,370 Views

How to Integrate Google Gemini to WhatsApp

February 16, 20241,658 Views

OpenAI Unveils Web-Based AI Agent Operator for Task Automation

January 24, 20251,502 Views
Our Picks

Ransomware 2.0: How AI Is Changing Cyber Attacks Forever

April 18, 2025

Lovable AI Faces Major Threat from VibeScamming Attacks

April 10, 2025

Top Trends to Include in Your Strategy for Digital Marketing in 2025

April 5, 2025

Subscribe to Updates

Get the latest creative news from FooBar about art, design and business.

Facebook X (Twitter) Instagram Pinterest
  • About Us
  • Contact Us
  • Tools
  • Terms & Conditions
  • Privacy Policy
  • AdSense Disclaimer
© 2025 Infovistar. Designed and Developed by Infovistar.

Type above and press Enter to search. Press Esc to cancel.

Go to mobile version