title: How to fix exo player slow loading of video
body: <p>I am trying to write an app where i'll have a couple of video URLs which i need to play. I am using ExoPlayer for playing videos.</p>
  
  <p>ExoPlayer is playing the videos but the problem i am facing is, ExoPlayer is loading some part of video (let's say 5 seconds) and then playing them and once exo player is done playing that part, it is trying to load next part of video and then playing that part of video. This problem is occurring even when the internet speed is good. </p>
  
  <p>I tried reading ExoPlayer docs and other stackoverflow posts but i am not able to figure out what's wrong here.   </p>
  
  <p>Below is my code for exo player's singleton class:  </p>
  
  <pre><code>/**
   * Singleton class that manages all video playback in the app. Ensures that only a single stream can be heard at a time
   * and reports the current playback status to any interested listeners.
   */
  public class VideoWrapper {
      private static String TAG = "VideoWrapper";
  
      private int VideoPlaybackState = VideoPlaybackListener.STATE_VIDEO_STOPPED;
  
      // Player that plays the videos.
      private SimpleExoPlayer exoPlayer;
  
      // Singleton instance of the class
      private static VideoWrapper videoWrapper;
  
      // URL of Current Video Item that is getting played.
      private String mCurrentStreamingUrl;
  
      // Handler to take request of video playback in-case there is a playlist is being sent for play.
      private Handler handler;
  
      // Add the listener and notify them if required. -- For demo i am not using it but for UI updates and all it will be useful.
      private List&lt;VideoPlaybackListener&gt; listeners = new LinkedList&lt;&gt;();
  
      // Tells to which screen we have to go back
      private String mPreviousScreenName;
  
      private Context context;
  
      public static VideoWrapper getInstance() {
          if (videoWrapper == null) {
              videoWrapper = new VideoWrapper();
          }
  
          return videoWrapper;
      }
  
      // Default constrructor!
      private VideoWrapper() {
          // Nothing to do.
      }
  
      public void setCurrentPreviousScreen(String screen) {
          mPreviousScreenName = screen;
      }
  
      public void init(Context context) {
          try {
              this.context = context;
              handler = new Handler(context.getMainLooper());
          } catch (Exception e) {
              // TODO
          }
      }
  
      public void stopAndReleasePlayer() {
  
          // Stop the player first.
          stopVideoStreaming();
  
          // Now release the player and make it null.
          if (exoPlayer != null) {
              exoPlayer.release();
              exoPlayer = null;
          }
      }
  
      public void addListener(VideoPlaybackListener listener) {
          listeners.add(listener);
      }
  
      public void removeListener(VideoPlaybackListener listener) {
          listeners.remove(listener);
      }
  
      public int getVideoPlaybackState() {
          return VideoPlaybackState;
      }
  
      private SimpleExoPlayer.VideoListener gVideoEventListener = new SimpleExoPlayer.VideoListener() {
          @Override
          public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
              // TODO: Do Something!
          }
  
          @Override
          public void onRenderedFirstFrame() {
              // TODO: Do Something!
          }
      };
  
      private ExoPlayer.EventListener eventListener = new ExoPlayer.EventListener() {
          @Override
          public void onTimelineChanged(Timeline timeline, Object manifest) {
              // TODO: Do Something!
          }
  
          @Override
          public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
              // TODO: Do Something!
          }
  
          @Override
          public void onLoadingChanged(boolean isLoading) {
              // TODO: Do Something!
          }
  
          @Override
          public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
              switch (playbackState) {
                  // playback state handling serially
                  case ExoPlayer.STATE_IDLE:
                      // TODO: Do something!
                      break;
  
                  case ExoPlayer.STATE_BUFFERING:
                      // TODO: Do something!
                      break;
  
                  case ExoPlayer.STATE_READY:
                      // TODO: Do something!
                      break;
  
                  case ExoPlayer.STATE_ENDED:
                      // TODO: Do something!
                      break;
              }
          }
  
          @Override
          public void onPlayerError(ExoPlaybackException error) {
              int errorType = error.type;
              switch (errorType) {
                  case ExoPlaybackException.TYPE_RENDERER:
                      // TODO: Do something!
                      break;
                  case ExoPlaybackException.TYPE_SOURCE:
                      // TODO: Do something!
                      break;
                  case ExoPlaybackException.TYPE_UNEXPECTED:
                      // TODO: Do something!
                      break;
                  default:
                      // TODO: Do something!
                      break;
              }
          }
  
          @Override
          public void onPositionDiscontinuity() {
              // TODO: Do something!
          }
      };
  
      private boolean canPlayCurrentItem() {
          return mCurrentStreamingUrl != null &amp;&amp; !TextUtils.isEmpty(mCurrentStreamingUrl);
      }
  
      public void stopVideoStreaming() {
          if (exoPlayer != null) {
              exoPlayer.setPlayWhenReady(false);
          }
      }
  
      private void restartVideoStreaming() {
          if (canPlayCurrentItem()) {
              streamCurrentTrack();
          }
      }
  
      public void startVideoStreaming(String streamUrl) {
          // Stop any video if it is playing.
          stopVideoStreaming();
          VideoPlaybackState = VideoPlaybackListener.STATE_VIDEO_STOPPED;
          mCurrentStreamingUrl = streamUrl;
  
          openStreamUrl();
      }
  
      private void openStreamUrl() {
          Uri uri = Uri.parse(mCurrentStreamingUrl);
  
          TrackSelector trackSelector = new DefaultTrackSelector();
  
          LoadControl loadControl = new DefaultLoadControl();
  
          DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
          DataSource.Factory dataSourceFactory = buildDataSourceFactory(bandwidthMeter);
  
          // This is the MediaSource representing the media to be played.
          HlsMediaSource mediaSource = new HlsMediaSource(uri, dataSourceFactory, handler, new AdaptiveMediaSourceEventListener() {
              @Override
              public void onLoadStarted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs) {
                  // TODO: Do something!
              }
  
              @Override
              public void onLoadCompleted(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) {
                  // TODO: Do something!
              }
  
              @Override
              public void onLoadCanceled(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) {
                  // TODO: Do something!
              }
  
              @Override
              public void onLoadError(DataSpec dataSpec, int dataType, int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaStartTimeMs, long mediaEndTimeMs, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded, IOException error, boolean wasCanceled) {
                  // TODO: Do something!
              }
  
              @Override
              public void onUpstreamDiscarded(int trackType, long mediaStartTimeMs, long mediaEndTimeMs) {
                  // TODO: Do something!
              }
  
              @Override
              public void onDownstreamFormatChanged(int trackType, Format trackFormat, int trackSelectionReason, Object trackSelectionData, long mediaTimeMs) {
                  // TODO: Do something!
              }
          });
  
          exoPlayer.prepare(mediaSource);
  
          streamCurrentTrack();
      }
  
      private DataSource.Factory buildDataSourceFactory(DefaultBandwidthMeter bandwidthMeter){
          return new DefaultDataSourceFactory(context, bandwidthMeter, buildHttpDataSourceFactory(bandwidthMeter));
      }
  
      private HttpDataSource.Factory buildHttpDataSourceFactory(DefaultBandwidthMeter bandwidthMeter){
          return new DefaultHttpDataSourceFactory("TiVoPhoenix", bandwidthMeter);
      }
  
      public void togglePlayPause() {
          if (canPlayCurrentItem()) {
              if (VideoPlaybackState == PlaybackListener.STATE_PLAYING) {
                  stopVideoStreaming();
                  VideoPlaybackState = PlaybackListener.STATE_PAUSED;
              } else {
                  restartVideoStreaming();
              }
          }
      }
  
      private void streamCurrentTrack() {
          VideoPlaybackState = VideoPlaybackListener.STATE_VIDEO_PLAYING;
          exoPlayer.setPlayWhenReady(true);
      }
  
      public SimpleExoPlayer getPlayer() {
          TrackSelector trackSelector = new DefaultTrackSelector();
          LoadControl loadControl = new DefaultLoadControl();
  
          // Stop and release the video player before re-creating it.
          stopAndReleasePlayer();
  
          exoPlayer = ExoPlayerFactory.newSimpleInstance(context, trackSelector, loadControl);
          exoPlayer.addListener(eventListener);
          exoPlayer.setVideoListener(gVideoEventListener);
  
          return exoPlayer;
      }
  }  
  </code></pre>
  
  <p>Can someone help me with this?</p>